')
+ .should('contain', 'tester: {
+ cy.get('.instance .instance:nth-child(2) .arrow-wrapper').click()
+ cy.get('.instance .instance .instance:nth-child(1) .item-name').click()
+ cy.get('.right .data-wrapper')
+ .should('contain', '$attrs')
+ .should('contain', 'attr:"some-attr"')
+ })
+})
diff --git a/vue-devtools/cypress/integration/events-tab.js b/vue-devtools/cypress/integration/events-tab.js
new file mode 100644
index 0000000000000000000000000000000000000000..d7fbbcc2a0dc40095fdff723eed4bd76c0b91a13
--- /dev/null
+++ b/vue-devtools/cypress/integration/events-tab.js
@@ -0,0 +1,37 @@
+import { suite } from '../utils/suite'
+
+suite('events tab', () => {
+ it('should display new events counter', () => {
+ cy.get('#target').iframe().then(({ get }) => {
+ get('.btn-emit-event').click({ force: true })
+ get('.btn-emit-event1').click({ force: true })
+ get('.btn-emit-event2').click({ force: true })
+ })
+ cy.get('.events-tab .tag').contains(3)
+ cy.get('.events-tab').click()
+ cy.get('.events-tab .tag').should('not.be.visible')
+ })
+
+ it('should display events', () => {
+ cy.get('.history .entry').should('have.length', 3)
+ })
+
+ it('should add event', () => {
+ cy.get('#target').iframe().then(({ get }) => {
+ get('.btn-emit-log-event').click({ force: true })
+ })
+ cy.get('.history .entry').should('have.length', 4)
+ })
+
+ it('should search events', () => {
+ cy.get('.left .search input').clear().type('event')
+ cy.get('.history .entry[data-active="true"]').should('have.length', 3)
+ cy.get('.left .search input').clear().type('')
+ cy.get('.history .entry[data-active="true"]').should('have.length', 1)
+ cy.get('.left .search input').clear().type('/^event$/')
+ cy.get('.history .entry[data-active="true"]').should('have.length', 1)
+ cy.get('.left .search input').clear()
+ cy.get('.button.reset').click()
+ cy.get('.history .entry[data-active="true"]').should('have.length', 0)
+ })
+})
diff --git a/vue-devtools/cypress/integration/vuex-edit.js b/vue-devtools/cypress/integration/vuex-edit.js
new file mode 100644
index 0000000000000000000000000000000000000000..1f3bc21ed5c35e98b39b9453301778a25a29622f
--- /dev/null
+++ b/vue-devtools/cypress/integration/vuex-edit.js
@@ -0,0 +1,111 @@
+import { suite } from '../utils/suite'
+
+suite('vuex edit', () => {
+ it('should edit state using the decrease button', () => {
+ cy.get('.vuex-tab').click()
+ cy.get('[data-id="load-vuex-state"]').click()
+
+ // using the decrease button
+ cy.get('.state .data-field').eq(0)
+ .find('.actions .vue-ui-button').eq(1)
+ .click({ force: true })
+
+ cy.get('.vuex-state-inspector').within(() => {
+ cy.get('.key').contains('count').parent().contains('-1')
+ })
+
+ cy.get('.state .data-field').eq(0)
+ .find('.actions .vue-ui-button').eq(1)
+ .click({ force: true })
+
+ cy.get('.vuex-state-inspector').within(() => {
+ cy.get('.key').contains('count').parent().contains('-2')
+ })
+
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#counter p').contains('-2')
+ })
+ })
+
+ it('should edit state using the increase button', () => {
+ // using the increase button
+ cy.get('.state .data-field').eq(0).click()
+ .find('.actions .vue-ui-button').eq(2)
+ .click({ force: true })
+
+ cy.get('.vuex-state-inspector').within(() => {
+ cy.get('.key').contains('count').parent().contains('-1')
+ })
+
+ cy.get('.state .data-field').eq(0).click()
+ .find('.actions .vue-ui-button').eq(2)
+ .click({ force: true })
+
+ cy.get('.vuex-state-inspector').within(() => {
+ cy.get('.key').contains('count').parent().contains('0')
+ })
+
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#counter p').contains('0')
+ })
+ })
+
+ it('should edit state using the edit input', () => {
+ // using the edit input
+ cy.get('.state .data-field').eq(0).click()
+ .find('.actions .vue-ui-button').eq(0).click({ force: true })
+ cy.get('.edit-input').type('12')
+ cy.get('.edit-overlay > .actions > :nth-child(2) > .content > .vue-ui-icon').click()
+
+ cy.wait(200)
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#counter p').contains('12')
+ })
+
+ // change count back to 1
+ cy.get('.state .data-field').eq(0).click()
+ .find('.actions .vue-ui-button').eq(0).click({ force: true })
+ cy.get('.edit-input').type('0')
+ cy.get('.edit-overlay > .actions > :nth-child(2) > .content > .vue-ui-icon').click()
+
+ cy.wait(200)
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#counter p').contains('0')
+ })
+ })
+
+ it('should edit state nested field', () => {
+ // using the decrease button
+ cy.get('.data-field > .children > .data-field').eq(4)
+ .find('.actions .vue-ui-button').eq(1)
+ .click({ force: true })
+ .click({ force: true })
+
+ cy.wait(200)
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#vuex-object pre').contains('-2')
+ })
+
+ // using the increase button
+ cy.get('.data-field > .children > .data-field').eq(4)
+ .find('.actions .vue-ui-button').eq(2)
+ .click({ force: true })
+ .click({ force: true })
+
+ cy.wait(200)
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#vuex-object pre').contains('0')
+ })
+
+ // using the input
+ cy.get('.data-field > .children > .data-field').eq(4)
+ .find('.actions .vue-ui-button').eq(0).click({ force: true })
+ cy.get('.edit-input').eq(1).type('12')
+ cy.get('.edit-overlay > .actions > :nth-child(2) > .content > .vue-ui-icon').click()
+
+ cy.wait(200)
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#vuex-object pre').contains('12')
+ })
+ })
+})
diff --git a/vue-devtools/cypress/integration/vuex-tab.js b/vue-devtools/cypress/integration/vuex-tab.js
new file mode 100644
index 0000000000000000000000000000000000000000..9ab0214f1d52c568a2bcca479c8cca2491cbd47c
--- /dev/null
+++ b/vue-devtools/cypress/integration/vuex-tab.js
@@ -0,0 +1,214 @@
+import { suite } from '../utils/suite'
+
+suite('vuex tab', () => {
+ it('should display mutations history', () => {
+ cy.get('#target').iframe().then(({ get }) => {
+ get('.increment')
+ .click({ force: true })
+ .click({ force: true })
+ get('.decrement').click({ force: true })
+ get('#counter p').contains('1')
+ })
+ cy.get('.vuex-tab').click()
+ cy.get('.history .entry').should('have.length', 6)
+ cy.get('[data-id="load-vuex-state"]').click()
+ cy.get('.recording-vuex-state').should('not.be.visible')
+ cy.get('.loading-vuex-state').should('not.be.visible')
+ cy.get('.vuex-state-inspector')
+ .should('contain', 'type:"DECREMENT"')
+ .should('contain', 'count:1')
+ cy.get('.history .entry').eq(5).should('have.class', 'inspected').should('have.class', 'active')
+ })
+
+ it('should filter state & getters', () => {
+ cy.get('.right .search input').clear().type('cou')
+ cy.get('.data-field').should('have.length', 2)
+ cy.get('.right .search input').clear().type('no value')
+ cy.get('.data-field').should('have.length', 0)
+ cy.get('.right .search input').clear()
+ })
+
+ it('should filter history', () => {
+ cy.get('.left .search input').clear().type('inc')
+ cy.get('.history .entry[data-active="true"]').should('have.length', 2)
+ cy.get('.history .entry[data-active="true"].inspected').should('have.length', 0)
+ cy.get('.history .entry[data-active="true"].active').should('have.length', 0)
+
+ cy.get('.left .search input').clear().type('/dec/i')
+ cy.get('.history .entry[data-active="true"]').should('have.length', 1)
+ cy.get('.history .entry[data-active="true"].inspected').should('have.length', 0)
+ cy.get('.history .entry[data-active="true"].active').should('have.length', 0)
+
+ cy.get('.left .search input').clear().type('/dec)/i')
+ cy.get('.history .entry[data-active="true"]').should('have.length', 5)
+ cy.get('.history .entry[data-active="true"].inspected').should('have.length', 0)
+ cy.get('.history .entry[data-active="true"].active').should('have.length', 1)
+
+ cy.get('.left .search input').clear()
+ })
+
+ it('should inspect state', () => {
+ cy.get('.history .entry .mutation-type').eq(2).click()
+ cy.get('.history .entry').eq(2)
+ .should('have.class', 'inspected')
+ .should('not.have.class', 'active')
+ cy.get('.recording-vuex-state').should('not.be.visible')
+ cy.get('.loading-vuex-state').should('not.be.visible')
+ cy.get('.vuex-state-inspector').then((el) => {
+ expect(el.text()).to.include('type:"INCREMENT"')
+ expect(el.text()).to.include('count:2')
+ expect(el.text()).to.include('Error from getter')
+ })
+ cy.get('.data-field .key').contains('lastCountPayload').click()
+ cy.get('.vuex-state-inspector').then((el) => {
+ expect(el.text()).to.include('a:1')
+ expect(el.text()).to.include('b:Object')
+ })
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#counter p').contains('1')
+ })
+ })
+
+ it('should time-travel', () => {
+ cy.get('.history .entry[data-index="4"] .entry-actions .action-time-travel').click({ force: true })
+ cy.get('.history .entry[data-index="4"]')
+ .should('have.class', 'inspected')
+ .should('have.class', 'active')
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#counter p').contains('2')
+ })
+
+ cy.get('.history .entry[data-index="3"] .mutation-type').click({ force: true })
+ cy.get('.history .entry[data-index="3"]')
+ .should('have.class', 'inspected')
+ .should('not.have.class', 'active')
+ cy.get('.history .entry[data-index="4"]')
+ .should('not.have.class', 'inspected')
+ .should('have.class', 'active')
+ cy.get('.recording-vuex-state').should('not.be.visible')
+ cy.get('.loading-vuex-state').should('not.be.visible')
+ cy.get('.recording-vuex-state').should('not.be.visible')
+ cy.get('.vuex-state-inspector').then((el) => {
+ expect(el.text()).to.include('type:"INCREMENT"')
+ expect(el.text()).to.include('count:1')
+ })
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#counter p').contains('2')
+ })
+ cy.get('.history .entry[data-index="3"] .entry-actions .action-time-travel').click({ force: true })
+ cy.get('.history .entry[data-index="3"]')
+ .should('have.class', 'inspected')
+ .should('have.class', 'active')
+ cy.get('.history .entry[data-index="4"]')
+ .should('not.have.class', 'inspected')
+ .should('not.have.class', 'active')
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#counter p').contains('1')
+ })
+
+ // Base state
+ cy.get('.history .entry[data-index="0"] .mutation-type').click({ force: true })
+ cy.get('.history .entry[data-index="0"]')
+ .should('have.class', 'inspected')
+ .should('not.have.class', 'active')
+ cy.get('.vuex-state-inspector').then((el) => {
+ expect(el.text()).to.include('count:0')
+ })
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#counter p').contains('1')
+ })
+ cy.get('.history .entry[data-index="2"] .entry-actions .action-time-travel').click({ force: true })
+ cy.get('.history .entry[data-index="2"]')
+ .should('have.class', 'inspected')
+ .should('have.class', 'active')
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#counter p').contains('0')
+ })
+ })
+
+ it('should revert', () => {
+ cy.get('.history .entry[data-index="5"] .mutation-type').click({ force: true })
+ cy.get('.history .entry[data-index="5"]').find('.action-revert').click({ force: true })
+ cy.get('.history .entry[data-active="true"]').should('have.length', 5)
+ cy.get('.history .entry[data-index="4"]')
+ .should('have.class', 'inspected')
+ .should('have.class', 'active')
+ cy.get('.vuex-state-inspector').then((el) => {
+ expect(el.text()).to.include('count:2')
+ })
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#counter p').contains('2')
+ })
+ })
+
+ it('should commit', () => {
+ cy.get('.history .entry[data-index="4"] .action-commit').click({ force: true })
+ cy.get('.history .entry[data-active="true"]').should('have.length', 1)
+ cy.get('.history .entry[data-index="0"]')
+ .should('have.class', 'inspected')
+ .should('have.class', 'active')
+ cy.get('.vuex-state-inspector').then((el) => {
+ expect(el.text()).to.include('count:2')
+ })
+ cy.get('#target').iframe().then(({ get }) => {
+ get('#counter p').contains('2')
+ })
+ })
+
+ it('should display getters', () => {
+ cy.get('.vuex-state-inspector').within(() => {
+ cy.get('.key').contains('count').parent().contains('2')
+ cy.get('.key').contains('isPositive').parent().contains('true')
+ })
+ cy.get('#target').iframe().then(({ get }) => {
+ get('.decrement')
+ .click({ force: true })
+ .click({ force: true })
+ .click({ force: true })
+ get('#counter p').contains('-1')
+ })
+ cy.get('.history .entry[data-index="3"]').click({ force: true })
+ cy.get('.recording-vuex-state').should('not.be.visible')
+ cy.get('.loading-vuex-state').should('not.be.visible')
+ cy.get('.vuex-state-inspector').within(() => {
+ cy.get('.key').contains('count').parent().contains('-1')
+ cy.get('.key').contains('isPositive').parent().contains('false')
+ })
+ })
+
+ it('should toggle recording', () => {
+ cy.get('.toggle-recording')
+ .click()
+ .contains('Paused')
+ cy.get('.toggle-recording .svg-icon').should('not.have.class', 'enabled')
+ // should not record
+ cy.get('#target').iframe().then(({ get }) => {
+ get('.increment').click({ force: true })
+ })
+ cy.get('.history .entry[data-active="true"]').should('have.length', 4)
+ })
+
+ it('should copy vuex state', () => {
+ cy.get('.export').click()
+ cy.get('.export .message')
+ .contains('(Copied to clipboard!)')
+ .should('not.be.visible', { timeout: 5000 })
+ })
+
+ it('should import vuex state', () => {
+ cy.get('.import').click()
+ cy.get('.import-state').should('be.visible')
+ cy.get('.import-state textarea').clear().type('{{}invalid: json}')
+ cy.get('.message.invalid-json').should('be.visible')
+ cy.get('.import-state textarea').clear().type('{{}"count":42,"date":"[native Date Fri Dec 22 2017 10:12:04 GMT+0100 (CET)]","nested":{{}"foo":"meow"},"instant":{{}"hey":"hi"}}')
+ cy.wait(500)
+ cy.get('.message.invalid-json').should('not.be.visible')
+ cy.wait(500)
+ cy.get('.vuex-state-inspector').then((el) => {
+ expect(el.text()).to.include('count:42')
+ expect(el.text()).to.include(`date:${new Date('Fri Dec 22 2017 10:12:04 GMT+0100 (CET)')}`)
+ })
+ cy.get('.import').click()
+ cy.get('.import-state').should('not.be.visible')
+ })
+})
diff --git a/vue-devtools/cypress/plugins/index.js b/vue-devtools/cypress/plugins/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..1cb1467bfff5c4cd7b95260bfd072c0691287faf
--- /dev/null
+++ b/vue-devtools/cypress/plugins/index.js
@@ -0,0 +1,24 @@
+// ***********************************************************
+// This example plugins/index.js can be used to load plugins
+//
+// You can change the location of this file or turn off loading
+// the plugins file with the 'pluginsFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/plugins-guide
+// ***********************************************************
+
+// This function is called when a project is opened or re-opened (e.g. due to
+// the project's config changing)
+
+module.exports = (_on, _config) => {
+ // `on` is used to hook into various events Cypress emits
+ // `config` is the resolved Cypress config
+
+ // on('before:browser:launch', (browser = {}, args) => {
+ // if (browser.name === 'chrome') {
+ // args.push('--disable-site-isolation-trials')
+ // return args
+ // }
+ // })
+}
diff --git a/vue-devtools/cypress/support/commands.js b/vue-devtools/cypress/support/commands.js
new file mode 100644
index 0000000000000000000000000000000000000000..336ac74b8e4e347aeace1bd6396efee0b2aa8b7e
--- /dev/null
+++ b/vue-devtools/cypress/support/commands.js
@@ -0,0 +1,48 @@
+// ***********************************************
+// This example commands.js shows you how to
+// create various custom commands and overwrite
+// existing commands.
+//
+// For more comprehensive examples of custom
+// commands please read more here:
+// https://on.cypress.io/custom-commands
+// ***********************************************
+//
+//
+// -- This is a parent command --
+// Cypress.Commands.add("login", (email, password) => { ... })
+//
+//
+// -- This is a child command --
+// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
+//
+//
+// -- This is a dual command --
+// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
+//
+//
+// -- This is will overwrite an existing command --
+// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
+
+Cypress.Commands.add('vueCheckInit', () => {
+ cy.get('.message .text').should('be.visible', { timeout: 10000 }).then((el) => {
+ expect(el.text()).to.include('Ready. Detected Vue')
+ })
+ cy.get('.instance').eq(0).contains('Root')
+})
+
+// Add iframe support until becomes part of the framework
+Cypress.Commands.add('iframe', { prevSubject: 'element' }, ($iframe) => {
+ const get = selector => cy.wait(500).wrap($iframe.contents().find(selector))
+
+ const el = $iframe[0]
+ const iframeDoc = el.contentDocument || el.contentWindow.document
+ if (iframeDoc.readyState === 'complete') {
+ return Cypress.Promise.resolve({ body: $iframe.contents().find('body'), get })
+ }
+ return new Cypress.Promise((resolve) => {
+ $iframe.on('load', () => {
+ resolve({ body: $iframe.contents().find('body'), get })
+ })
+ })
+})
diff --git a/vue-devtools/cypress/support/index.js b/vue-devtools/cypress/support/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..d68db96df2697e0835f5c490db0c2cc81673f407
--- /dev/null
+++ b/vue-devtools/cypress/support/index.js
@@ -0,0 +1,20 @@
+// ***********************************************************
+// This example support/index.js is processed and
+// loaded automatically before your test files.
+//
+// This is a great place to put global configuration and
+// behavior that modifies Cypress.
+//
+// You can change the location of this file or turn off
+// automatically serving support files with the
+// 'supportFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/configuration
+// ***********************************************************
+
+// Import commands.js using ES2015 syntax:
+import './commands'
+
+// Alternatively you can use CommonJS syntax:
+// require('./commands')
diff --git a/vue-devtools/cypress/utils/suite.js b/vue-devtools/cypress/utils/suite.js
new file mode 100644
index 0000000000000000000000000000000000000000..d1eb6f127cb398dd18b30bf3137a1e3c72c09485
--- /dev/null
+++ b/vue-devtools/cypress/utils/suite.js
@@ -0,0 +1,9 @@
+export function suite(description, tests) {
+ describe(description, () => {
+ before(() => {
+ cy.visit('/')
+ cy.vueCheckInit()
+ })
+ tests()
+ })
+}
diff --git a/vue-devtools/dist/.gitkeep b/vue-devtools/dist/.gitkeep
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/vue-devtools/eslint.config.js b/vue-devtools/eslint.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..82cafd35fdef93815a0bea93671c21b22811bd84
--- /dev/null
+++ b/vue-devtools/eslint.config.js
@@ -0,0 +1,43 @@
+const antfu = require('@antfu/eslint-config').default
+
+module.exports = antfu({
+ ignores: [
+ '**/dist',
+ ],
+}, {
+ rules: {
+ 'curly': ['error', 'all'],
+ 'node/prefer-global/process': 'off',
+ },
+}, {
+ files: [
+ 'packages/shell-dev*/**',
+ ],
+ rules: {
+ 'no-console': 'off',
+ 'unused-imports/no-unused-vars': 'off',
+ 'vue/require-explicit-emits': 'off',
+ 'vue/custom-event-name-casing': 'off',
+ 'vue/no-deprecated-functional-template': 'off',
+ 'vue/no-deprecated-filter': 'off',
+ 'vue/no-unused-refs': 'off',
+ 'vue/require-component-is': 'off',
+ 'vue/return-in-computed-property': 'off',
+ },
+}, {
+ files: [
+ 'packages/shell-host/**',
+ ],
+ rules: {
+ 'no-console': 'off',
+ },
+}, {
+ files: [
+ 'package.json',
+ 'packages/*/package.json',
+ 'packages/*/manifest.json',
+ ],
+ rules: {
+ 'style/eol-last': 'off',
+ },
+})
diff --git a/vue-devtools/extension-zips.js b/vue-devtools/extension-zips.js
new file mode 100644
index 0000000000000000000000000000000000000000..b678ce9ce26ad0471dfd3c733b7fc188cd197f7f
--- /dev/null
+++ b/vue-devtools/extension-zips.js
@@ -0,0 +1,142 @@
+// require modules
+const fs = require('node:fs')
+const path = require('node:path')
+const process = require('node:process')
+const archiver = require('archiver')
+
+const IS_CI = !!(process.env.CIRCLECI || process.env.GITHUB_ACTIONS)
+const ProgressBar = !IS_CI ? require('progress') : {}
+const readDirGlob = !IS_CI ? require('readdir-glob') : {}
+
+const INCLUDE_GLOBS = [
+ 'build/**',
+ 'icons/**',
+ 'popups/**',
+ 'devtools.html',
+ 'devtools-background.html',
+ 'manifest.json',
+ 'package.json',
+]
+// SKIP_GLOBS makes glob searches more efficient
+const SKIP_DIR_GLOBS = ['node_modules', 'src']
+
+function bytesToSize(bytes) {
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
+ if (bytes === 0) {
+ return '0 Byte'
+ }
+ const i = Number.parseInt(Math.floor(Math.log(bytes) / Math.log(1024)))
+ return `${Math.round(bytes / 1024 ** i, 2)} ${sizes[i]}`
+}
+
+(async () => {
+ await writeZip('devtools-chrome.zip', 'shell-chrome')
+ await writeZip('devtools-firefox.zip', 'shell-firefox')
+
+ async function writeZip(fileName, packageDir) {
+ // create a file to stream archive data to.
+ const output = fs.createWriteStream(path.join(__dirname, 'dist', fileName))
+ const archive = archiver('zip', {
+ zlib: { level: 9 }, // Sets the compression level.
+ })
+
+ if (!IS_CI) {
+ const status = {
+ total: 0,
+ cFile: '...',
+ cSize: '0 Bytes',
+ tBytes: 0,
+ tSize: '0 Bytes',
+ }
+
+ async function parseFileStats() {
+ return new Promise((resolve, reject) => {
+ const globber = readDirGlob(path.join('packages', packageDir), { pattern: INCLUDE_GLOBS, skip: SKIP_DIR_GLOBS, mark: true, stat: true })
+ globber.on('match', (match) => {
+ if (!match.stat.isDirectory()) {
+ status.total++
+ }
+ })
+ globber.on('error', (err) => {
+ reject(err)
+ })
+ globber.on('end', () => {
+ resolve()
+ })
+ })
+ }
+ await parseFileStats().catch((err) => {
+ console.error(err)
+ process.exit(1)
+ })
+
+ const bar = new ProgressBar(`${fileName} @ :tSize [:bar] :current/:total :percent +:cFile@:cSize`, {
+ width: 18,
+ incomplete: ' ',
+ total: status.total,
+ })
+ bar.tick(0, status)
+
+ archive.on('entry', (entry) => {
+ if (!entry.stats.isDirectory()) {
+ const n = entry.name
+ status.written++
+ status.cFile = n.length > 14
+ ? `...${n.slice(n.length - 11)}`
+ : n
+ status.cSize = bytesToSize(entry.stats.size)
+ status.tBytes += entry.stats.size
+ status.tSize = bytesToSize(status.tBytes)
+ bar.tick(1, status)
+ }
+ })
+ }
+
+ const end = new Promise((resolve) => {
+ // listen for all archive data to be written
+ // 'close' event is fired only when a file descriptor is involved
+ output.on('close', () => {
+ if (archive.pointer() < 1000) {
+ console.warn(`Zip file (${fileName}) is only ${archive.pointer()} bytes`)
+ }
+ resolve()
+ })
+ })
+
+ // This event is fired when the data source is drained no matter what was the data source.
+ // It is not part of this library but rather from the NodeJS Stream API.
+ // @see: https://nodejs.org/api/stream.html#stream_event_end
+ output.on('end', () => {
+ 'nothing'
+ })
+
+ // good practice to catch warnings (ie stat failures and other non-blocking errors)
+ archive.on('warning', (err) => {
+ if (err.code !== 'ENOENT') {
+ // throw error
+ console.error(err)
+ process.exit(1)
+ }
+ })
+
+ // good practice to catch this error explicitly
+ archive.on('error', (err) => {
+ console.error(err)
+ process.exit(1)
+ })
+
+ // pipe archive data to the file
+ archive.pipe(output)
+
+ INCLUDE_GLOBS.forEach((glob) => {
+ // append files from a glob pattern
+ archive.glob(glob, { cwd: path.join('packages', packageDir), skip: SKIP_DIR_GLOBS })
+ })
+
+ // finalize the archive (ie we are done appending files but streams have to finish yet)
+ // 'close', 'end' or 'finish' may be fired right after calling this method so register to them beforehand
+ archive.finalize()
+
+ await end
+ }
+})()
diff --git a/vue-devtools/lerna.json b/vue-devtools/lerna.json
new file mode 100644
index 0000000000000000000000000000000000000000..a2cb47c994851c14059bff03bdcc56e9687e5725
--- /dev/null
+++ b/vue-devtools/lerna.json
@@ -0,0 +1,11 @@
+{
+ "npmClient": "yarn",
+ "useWorkspaces": true,
+ "version": "6.0.0-beta.2",
+ "packages": [
+ "packages/*"
+ ],
+ "ignoreChanges": [
+ "**/*.md"
+ ]
+}
diff --git a/vue-devtools/media/chrome-webstore/screenshot1-size.png b/vue-devtools/media/chrome-webstore/screenshot1-size.png
new file mode 100644
index 0000000000000000000000000000000000000000..c34fad7959b10ffa6f7fc4fc4b047d06a6050555
--- /dev/null
+++ b/vue-devtools/media/chrome-webstore/screenshot1-size.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e3874b539d5004ce2941d13255d4b546ba466237ef6d10f5adbba031e5455cb1
+size 129791
diff --git a/vue-devtools/media/chrome-webstore/screenshot1.png b/vue-devtools/media/chrome-webstore/screenshot1.png
new file mode 100644
index 0000000000000000000000000000000000000000..abadd382dc793db6ad456766e89a27f3b198fa7b
--- /dev/null
+++ b/vue-devtools/media/chrome-webstore/screenshot1.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9ac3cbf7afbade2a16a77c36b5866cc0404544533121016ccf46bab3c7f8c5ee
+size 120080
diff --git a/vue-devtools/media/chrome-webstore/screenshot2-size.png b/vue-devtools/media/chrome-webstore/screenshot2-size.png
new file mode 100644
index 0000000000000000000000000000000000000000..c5a4f2439d08b8ce54104116c4c6d82c8e0ef453
Binary files /dev/null and b/vue-devtools/media/chrome-webstore/screenshot2-size.png differ
diff --git a/vue-devtools/media/chrome-webstore/screenshot2.png b/vue-devtools/media/chrome-webstore/screenshot2.png
new file mode 100644
index 0000000000000000000000000000000000000000..036441016f17ec8d6bf6d1c24b8f5a4fb2e3a078
Binary files /dev/null and b/vue-devtools/media/chrome-webstore/screenshot2.png differ
diff --git a/vue-devtools/media/chrome-webstore/screenshot3-size.png b/vue-devtools/media/chrome-webstore/screenshot3-size.png
new file mode 100644
index 0000000000000000000000000000000000000000..9768258940c95b48a0b01fde2b3722bf40892567
Binary files /dev/null and b/vue-devtools/media/chrome-webstore/screenshot3-size.png differ
diff --git a/vue-devtools/media/chrome-webstore/screenshot3.png b/vue-devtools/media/chrome-webstore/screenshot3.png
new file mode 100644
index 0000000000000000000000000000000000000000..95359767a0de7c5cb3936524b5febb50d5f9b915
Binary files /dev/null and b/vue-devtools/media/chrome-webstore/screenshot3.png differ
diff --git a/vue-devtools/media/chrome-webstore/screenshot4-size.png b/vue-devtools/media/chrome-webstore/screenshot4-size.png
new file mode 100644
index 0000000000000000000000000000000000000000..574b26a93050a196d217bc66dcf7813ef3d9fe68
Binary files /dev/null and b/vue-devtools/media/chrome-webstore/screenshot4-size.png differ
diff --git a/vue-devtools/media/chrome-webstore/screenshot4.png b/vue-devtools/media/chrome-webstore/screenshot4.png
new file mode 100644
index 0000000000000000000000000000000000000000..0ba8e411479c6a50186e1cbf045145db243bfeb3
Binary files /dev/null and b/vue-devtools/media/chrome-webstore/screenshot4.png differ
diff --git a/vue-devtools/media/screenshot-rounded.png b/vue-devtools/media/screenshot-rounded.png
new file mode 100644
index 0000000000000000000000000000000000000000..4fe55fe4f0984cf713befedac781985ce17789af
--- /dev/null
+++ b/vue-devtools/media/screenshot-rounded.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d9eecaf9087bdc6bea62f51695757239a41a455430b49a6946ab5513f6efb62f
+size 159951
diff --git a/vue-devtools/media/screenshot-shadow.png b/vue-devtools/media/screenshot-shadow.png
new file mode 100644
index 0000000000000000000000000000000000000000..57a7a65f12d94c394b6e2642e87c8d02552175e8
--- /dev/null
+++ b/vue-devtools/media/screenshot-shadow.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3a053a8234a79608e810346df0524a1ee5ce77bec29b83739ce2126d81c794ec
+size 165677
diff --git a/vue-devtools/media/screenshot.png b/vue-devtools/media/screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..eef1e41a6c06d195a03decf22c1bde0841f4d87b
--- /dev/null
+++ b/vue-devtools/media/screenshot.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6a795f9c7e3d5915d7c8030a2b7514aaa068765af47543b3c2615c0ef0deac51
+size 152023
diff --git a/vue-devtools/package.json b/vue-devtools/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..3e31d92d9139feb29f662d1aa84352d376f2f45e
--- /dev/null
+++ b/vue-devtools/package.json
@@ -0,0 +1,76 @@
+{
+ "name": "vue-devtools",
+ "version": "6.6.3",
+ "private": true,
+ "description": "devtools for Vue.js!",
+ "workspaces": [
+ "packages/*"
+ ],
+ "author": "Evan You",
+ "license": "MIT",
+ "homepage": "https://github.com/vuejs/vue-devtools#readme",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/vuejs/vue-devtools.git"
+ },
+ "bugs": {
+ "url": "https://github.com/vuejs/vue-devtools/issues"
+ },
+ "engines": {
+ "node": ">=8.10"
+ },
+ "scripts": {
+ "dev:vue2": "concurrently \"cd packages/shell-dev-vue2 && yarn dev\" \"cd packages/shell-host && yarn dev\"",
+ "dev:vue3": "concurrently \"cd packages/shell-dev-vue3 && yarn dev\" \"cd packages/shell-host && yarn dev\"",
+ "dev:chrome": "cd packages/shell-chrome && webpack --watch",
+ "dev:chrome:prod": "cd packages/shell-chrome && cross-env NODE_ENV=production webpack --watch",
+ "dev:firefox": "cd packages/shell-firefox && webpack --watch",
+ "dev:electron": "cd packages/shell-electron && npm run dev",
+ "build": "lerna run build",
+ "build:watch": "lerna run build --scope @vue-devtools/app-backend* --scope @vue-devtools/shared-* --scope @vue/devtools-api && lerna run build:watch --stream --no-sort --concurrency 99",
+ "lint": "eslint .",
+ "run:firefox": "web-ext run -s packages/shell-firefox -a dist -i src -u http://localhost:8090/target.html",
+ "zip": "node ./extension-zips.js",
+ "sign:firefox": "node ./sign-firefox.js",
+ "release": "npm run test && node release.js && npm run build && npm run zip && npm run pub",
+ "release:beta": "cross-env RELEASE_CHANNEL=beta npm run release && npm run sign:firefox",
+ "pub": "npm run pub:electron && npm run pub:api",
+ "pub:electron": "cd packages/shell-electron && npm publish",
+ "pub:api": "cd packages/api && npm publish",
+ "test": "npm run lint && npm run test:types:front",
+ "test:types:front": "tsc --noEmit",
+ "test:e2e": "cross-env PORT=4040 start-server-and-test dev:shell http://localhost:4040 test:e2e:run",
+ "test:e2e:run": "cypress run --config baseUrl=http://localhost:4040",
+ "test:open": "cypress open --config baseUrl=http://localhost:8100",
+ "docs:dev": "cd packages/docs && vitepress dev src",
+ "docs:build": "cd packages/docs && vitepress build src",
+ "docs:serve": "cd packages/docs && vitepress serve src"
+ },
+ "devDependencies": {
+ "@antfu/eslint-config": "^2.19.1",
+ "@tailwindcss/postcss7-compat": "^2.0.4",
+ "@types/chrome": "^0.0.139",
+ "@types/speakingurl": "^13.0.3",
+ "archiver": "^5.3.0",
+ "autoprefixer": "^9.1.5",
+ "concurrently": "^5.1.0",
+ "cross-env": "^5.2.0",
+ "cypress": "^3.1.0",
+ "eslint": "^9.3.0",
+ "execa": "^4.0.3",
+ "inquirer": "^6.2.0",
+ "lerna": "^4.0.0",
+ "postcss-nested": "^4.2.1",
+ "rimraf": "^3.0.2",
+ "semver": "^5.5.1",
+ "start-server-and-test": "^1.7.1",
+ "svg-inline-loader": "^0.8.2",
+ "tailwindcss": "npm:@tailwindcss/postcss7-compat",
+ "vue-loader": "^17.2.2",
+ "webpack-dev-server": "^4.15.1"
+ },
+ "resolutions": {
+ "cypress": "=3.4.1",
+ "webpack-dev-server": "^4.15.1"
+ }
+}
\ No newline at end of file
diff --git a/vue-devtools/packages/api/package.json b/vue-devtools/packages/api/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..772d56664b4efeac9bd9571beb7d3363fb73d0b6
--- /dev/null
+++ b/vue-devtools/packages/api/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "@vue/devtools-api",
+ "version": "6.6.3",
+ "description": "Interact with the Vue devtools from the page",
+ "author": {
+ "name": "Guillaume Chau"
+ },
+ "license": "MIT",
+ "repository": {
+ "url": "https://github.com/vuejs/vue-devtools.git",
+ "type": "git",
+ "directory": "packages/api"
+ },
+ "sideEffects": false,
+ "main": "lib/cjs/index.js",
+ "browser": "lib/esm/index.js",
+ "module": "lib/esm/index.js",
+ "types": "lib/esm/index.d.ts",
+ "files": [
+ "lib/cjs",
+ "lib/esm"
+ ],
+ "publishConfig": {
+ "access": "public"
+ },
+ "scripts": {
+ "build": "rimraf lib && yarn build:esm && yarn build:cjs",
+ "build:esm": "tsc --module es2015 --outDir lib/esm -d",
+ "build:cjs": "tsc --module commonjs --outDir lib/cjs",
+ "build:watch": "yarn tsc --module es2015 --outDir lib/esm -d -w --sourceMap"
+ },
+ "devDependencies": {
+ "@types/node": "^20.11.16",
+ "@types/webpack-env": "^1.15.1",
+ "typescript": "^5.3.3"
+ }
+}
\ No newline at end of file
diff --git a/vue-devtools/packages/api/src/api/api.ts b/vue-devtools/packages/api/src/api/api.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ab46a7e4d9fee8ac921d2816014bdba48d0c5b55
--- /dev/null
+++ b/vue-devtools/packages/api/src/api/api.ts
@@ -0,0 +1,122 @@
+import type { ComponentBounds, Hookable } from './hooks.js'
+import type { Context } from './context.js'
+import type { ComponentInstance, ComponentState, StateBase } from './component.js'
+import type { App } from './app.js'
+import type { ID } from './util.js'
+
+export interface DevtoolsPluginApi {
+ on: Hookable
+ notifyComponentUpdate: (instance?: ComponentInstance) => void
+ addTimelineLayer: (options: TimelineLayerOptions) => void
+ addTimelineEvent: (options: TimelineEventOptions) => void
+ addInspector: (options: CustomInspectorOptions) => void
+ sendInspectorTree: (inspectorId: string) => void
+ sendInspectorState: (inspectorId: string) => void
+ selectInspectorNode: (inspectorId: string, nodeId: string) => void
+ getComponentBounds: (instance: ComponentInstance) => Promise
+ getComponentName: (instance: ComponentInstance) => Promise
+ getComponentInstances: (app: App) => Promise
+ highlightElement: (instance: ComponentInstance) => void
+ unhighlightElement: () => void
+ getSettings: (pluginId?: string) => TSettings
+ now: () => number
+ /**
+ * @private
+ */
+ setSettings: (values: TSettings) => void
+}
+
+export interface AppRecord {
+ id: string
+ name: string
+ instanceMap: Map
+ rootInstance: ComponentInstance
+}
+
+export interface TimelineLayerOptions {
+ id: string
+ label: string
+ color: number
+ skipScreenshots?: boolean
+ groupsOnly?: boolean
+ ignoreNoDurationGroups?: boolean
+ screenshotOverlayRender?: (event: TimelineEvent & ScreenshotOverlayEvent, ctx: ScreenshotOverlayRenderContext) => ScreenshotOverlayRenderResult | Promise
+}
+
+export interface ScreenshotOverlayEvent {
+ layerId: string
+ renderMeta: any
+}
+
+export interface ScreenshotOverlayRenderContext {
+ screenshot: ScreenshotData
+ events: (TimelineEvent & ScreenshotOverlayEvent)[]
+ index: number
+}
+
+export type ScreenshotOverlayRenderResult = HTMLElement | string | false
+
+export interface ScreenshotData {
+ time: number
+}
+
+export interface TimelineEventOptions {
+ layerId: string
+ event: TimelineEvent
+ all?: boolean
+}
+
+export interface TimelineEvent {
+ time: number
+ data: TData
+ logType?: 'default' | 'warning' | 'error'
+ meta?: TMeta
+ groupId?: ID
+ title?: string
+ subtitle?: string
+}
+
+export interface TimelineMarkerOptions {
+ id: string
+ time: number
+ color: number
+ label: string
+ all?: boolean
+}
+
+export interface CustomInspectorOptions {
+ id: string
+ label: string
+ icon?: string
+ treeFilterPlaceholder?: string
+ stateFilterPlaceholder?: string
+ noSelectionText?: string
+ actions?: {
+ icon: string
+ tooltip?: string
+ action: () => void | Promise
+ }[]
+ nodeActions?: {
+ icon: string
+ tooltip?: string
+ action: (nodeId: string) => void | Promise
+ }[]
+}
+
+export interface CustomInspectorNode {
+ id: string
+ label: string
+ children?: CustomInspectorNode[]
+ tags?: InspectorNodeTag[]
+}
+
+export interface InspectorNodeTag {
+ label: string
+ textColor: number
+ backgroundColor: number
+ tooltip?: string
+}
+
+export interface CustomInspectorState {
+ [key: string]: (StateBase | Omit)[]
+}
diff --git a/vue-devtools/packages/api/src/api/app.ts b/vue-devtools/packages/api/src/api/app.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9873b8c540405be79af9ecf67fdec492fd838188
--- /dev/null
+++ b/vue-devtools/packages/api/src/api/app.ts
@@ -0,0 +1 @@
+export type App = any // @TODO
diff --git a/vue-devtools/packages/api/src/api/component.ts b/vue-devtools/packages/api/src/api/component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9b6d934865c0ffdcfd6a37a1da091e7e0aa12529
--- /dev/null
+++ b/vue-devtools/packages/api/src/api/component.ts
@@ -0,0 +1,89 @@
+import type { InspectorNodeTag } from './api.js'
+import type { ID } from './util.js'
+
+export type ComponentInstance = any // @TODO
+
+export interface ComponentTreeNode {
+ uid: ID
+ id: string
+ name: string
+ renderKey: string | number
+ inactive: boolean
+ isFragment: boolean
+ hasChildren: boolean
+ children: ComponentTreeNode[]
+ domOrder?: number[]
+ consoleId?: string
+ isRouterView?: boolean
+ macthedRouteSegment?: string
+ tags: InspectorNodeTag[]
+ autoOpen: boolean
+ meta?: any
+}
+
+export interface InspectedComponentData {
+ id: string
+ name: string
+ file: string
+ state: ComponentState[]
+ functional?: boolean
+}
+
+export interface StateBase {
+ key: string
+ value: any
+ editable?: boolean
+ objectType?: 'ref' | 'reactive' | 'computed' | 'other'
+ raw?: string
+}
+
+export interface ComponentStateBase extends StateBase {
+ type: string
+}
+
+export interface ComponentPropState extends ComponentStateBase {
+ meta?: {
+ type: string
+ required: boolean
+ /** Vue 1 only */
+ mode?: 'default' | 'sync' | 'once'
+ }
+}
+
+export type ComponentBuiltinCustomStateTypes = 'function' | 'map' | 'set' | 'reference' | 'component' | 'component-definition' | 'router' | 'store'
+
+export interface ComponentCustomState extends ComponentStateBase {
+ value: CustomState
+}
+
+export interface CustomState {
+ _custom: {
+ type: ComponentBuiltinCustomStateTypes | string
+ objectType?: string
+ display?: string
+ tooltip?: string
+ value?: any
+ abstract?: boolean
+ file?: string
+ uid?: number
+ readOnly?: boolean
+ /** Configure immediate child fields */
+ fields?: {
+ abstract?: boolean
+ }
+ id?: any
+ actions?: {
+ icon: string
+ tooltip?: string
+ action: () => void | Promise
+ }[]
+ /** internal */
+ _reviveId?: number
+ }
+}
+
+export type ComponentState = ComponentStateBase | ComponentPropState | ComponentCustomState
+
+export interface ComponentDevtoolsOptions {
+ hide?: boolean
+}
diff --git a/vue-devtools/packages/api/src/api/context.ts b/vue-devtools/packages/api/src/api/context.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4b6b255039270ad64b37bec8752317c0e3271307
--- /dev/null
+++ b/vue-devtools/packages/api/src/api/context.ts
@@ -0,0 +1,6 @@
+import type { AppRecord } from './api.js'
+
+export interface Context {
+ currentTab: string
+ currentAppRecord: AppRecord
+}
diff --git a/vue-devtools/packages/api/src/api/hooks.ts b/vue-devtools/packages/api/src/api/hooks.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8a88a619f7e1e93d0b74461348d70fc619a3cd21
--- /dev/null
+++ b/vue-devtools/packages/api/src/api/hooks.ts
@@ -0,0 +1,187 @@
+import type { ComponentDevtoolsOptions, ComponentInstance, ComponentTreeNode, InspectedComponentData } from './component.js'
+import type { App } from './app.js'
+import type { CustomInspectorNode, CustomInspectorState, TimelineEvent } from './api.js'
+
+// eslint-disable-next-line no-restricted-syntax
+export const enum Hooks {
+ TRANSFORM_CALL = 'transformCall',
+ GET_APP_RECORD_NAME = 'getAppRecordName',
+ GET_APP_ROOT_INSTANCE = 'getAppRootInstance',
+ REGISTER_APPLICATION = 'registerApplication',
+ WALK_COMPONENT_TREE = 'walkComponentTree',
+ VISIT_COMPONENT_TREE = 'visitComponentTree',
+ WALK_COMPONENT_PARENTS = 'walkComponentParents',
+ INSPECT_COMPONENT = 'inspectComponent',
+ GET_COMPONENT_BOUNDS = 'getComponentBounds',
+ GET_COMPONENT_NAME = 'getComponentName',
+ GET_COMPONENT_INSTANCES = 'getComponentInstances',
+ GET_ELEMENT_COMPONENT = 'getElementComponent',
+ GET_COMPONENT_ROOT_ELEMENTS = 'getComponentRootElements',
+ EDIT_COMPONENT_STATE = 'editComponentState',
+ GET_COMPONENT_DEVTOOLS_OPTIONS = 'getAppDevtoolsOptions',
+ GET_COMPONENT_RENDER_CODE = 'getComponentRenderCode',
+ INSPECT_TIMELINE_EVENT = 'inspectTimelineEvent',
+ TIMELINE_CLEARED = 'timelineCleared',
+ GET_INSPECTOR_TREE = 'getInspectorTree',
+ GET_INSPECTOR_STATE = 'getInspectorState',
+ EDIT_INSPECTOR_STATE = 'editInspectorState',
+ SET_PLUGIN_SETTINGS = 'setPluginSettings',
+}
+
+export interface ComponentBounds {
+ left: number
+ top: number
+ width: number
+ height: number
+}
+
+export interface HookPayloads {
+ [Hooks.TRANSFORM_CALL]: {
+ callName: string
+ inArgs: any[]
+ outArgs: any[]
+ }
+ [Hooks.GET_APP_RECORD_NAME]: {
+ app: App
+ name: string
+ }
+ [Hooks.GET_APP_ROOT_INSTANCE]: {
+ app: App
+ root: ComponentInstance
+ }
+ [Hooks.REGISTER_APPLICATION]: {
+ app: App
+ }
+ [Hooks.WALK_COMPONENT_TREE]: {
+ componentInstance: ComponentInstance
+ componentTreeData: ComponentTreeNode[]
+ maxDepth: number
+ filter: string
+ recursively: boolean
+ }
+ [Hooks.VISIT_COMPONENT_TREE]: {
+ app: App
+ componentInstance: ComponentInstance
+ treeNode: ComponentTreeNode
+ filter: string
+ }
+ [Hooks.WALK_COMPONENT_PARENTS]: {
+ componentInstance: ComponentInstance
+ parentInstances: ComponentInstance[]
+ }
+ [Hooks.INSPECT_COMPONENT]: {
+ app: App
+ componentInstance: ComponentInstance
+ instanceData: InspectedComponentData
+ }
+ [Hooks.GET_COMPONENT_BOUNDS]: {
+ componentInstance: ComponentInstance
+ bounds: ComponentBounds
+ }
+ [Hooks.GET_COMPONENT_NAME]: {
+ componentInstance: ComponentInstance
+ name: string
+ }
+ [Hooks.GET_COMPONENT_INSTANCES]: {
+ app: App
+ componentInstances: ComponentInstance[]
+ }
+ [Hooks.GET_ELEMENT_COMPONENT]: {
+ element: HTMLElement | any
+ componentInstance: ComponentInstance
+ }
+ [Hooks.GET_COMPONENT_ROOT_ELEMENTS]: {
+ componentInstance: ComponentInstance
+ rootElements: (HTMLElement | any)[]
+ }
+ [Hooks.EDIT_COMPONENT_STATE]: {
+ app: App
+ componentInstance: ComponentInstance
+ path: string[]
+ type: string
+ state: EditStatePayload
+ set: (object: any, path?: string | (string[]), value?: any, cb?: (object: any, field: string, value: any) => void) => void
+ }
+ [Hooks.GET_COMPONENT_DEVTOOLS_OPTIONS]: {
+ componentInstance: ComponentInstance
+ options: ComponentDevtoolsOptions
+ }
+ [Hooks.GET_COMPONENT_RENDER_CODE]: {
+ componentInstance: ComponentInstance
+ code: string
+ }
+ [Hooks.INSPECT_TIMELINE_EVENT]: {
+ app: App
+ layerId: string
+ event: TimelineEvent
+ all?: boolean
+ data: any
+ }
+ [Hooks.TIMELINE_CLEARED]: Record
+ [Hooks.GET_INSPECTOR_TREE]: {
+ app: App
+ inspectorId: string
+ filter: string
+ rootNodes: CustomInspectorNode[]
+ }
+ [Hooks.GET_INSPECTOR_STATE]: {
+ app: App
+ inspectorId: string
+ nodeId: string
+ state: CustomInspectorState
+ }
+ [Hooks.EDIT_INSPECTOR_STATE]: {
+ app: App
+ inspectorId: string
+ nodeId: string
+ path: string[]
+ type: string
+ state: EditStatePayload
+ set: (object: any, path?: string | (string[]), value?: any, cb?: (object: any, field: string, value: any) => void) => void
+ }
+ [Hooks.SET_PLUGIN_SETTINGS]: {
+ app: App
+ pluginId: string
+ key: string
+ newValue: any
+ oldValue: any
+ settings: any
+ }
+}
+
+export type EditStatePayload = {
+ value: any
+ newKey?: string | null
+ remove?: undefined | false
+} | {
+ value?: undefined
+ newKey?: undefined
+ remove: true
+}
+
+export type HookHandler = (payload: TPayload, ctx: TContext) => void | Promise
+
+export interface Hookable {
+ transformCall: (handler: HookHandler) => any
+ getAppRecordName: (handler: HookHandler) => any
+ getAppRootInstance: (handler: HookHandler) => any
+ registerApplication: (handler: HookHandler) => any
+ walkComponentTree: (handler: HookHandler) => any
+ visitComponentTree: (handler: HookHandler) => any
+ walkComponentParents: (handler: HookHandler) => any
+ inspectComponent: (handler: HookHandler) => any
+ getComponentBounds: (handler: HookHandler) => any
+ getComponentName: (handler: HookHandler) => any
+ getComponentInstances: (handler: HookHandler) => any
+ getElementComponent: (handler: HookHandler) => any
+ getComponentRootElements: (handler: HookHandler) => any
+ editComponentState: (handler: HookHandler) => any
+ getComponentDevtoolsOptions: (handler: HookHandler) => any
+ getComponentRenderCode: (handler: HookHandler) => any
+ inspectTimelineEvent: (handler: HookHandler) => any
+ timelineCleared: (handler: HookHandler) => any
+ getInspectorTree: (handler: HookHandler) => any
+ getInspectorState: (handler: HookHandler) => any
+ editInspectorState: (handler: HookHandler) => any
+ setPluginSettings: (handler: HookHandler) => any
+}
diff --git a/vue-devtools/packages/api/src/api/index.ts b/vue-devtools/packages/api/src/api/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..06510db1b45c2dfa9ffd7618d8ca746f1275c0c3
--- /dev/null
+++ b/vue-devtools/packages/api/src/api/index.ts
@@ -0,0 +1,6 @@
+export * from './api.js'
+export * from './app.js'
+export * from './component.js'
+export * from './context.js'
+export * from './hooks.js'
+export * from './util.js'
diff --git a/vue-devtools/packages/api/src/api/util.ts b/vue-devtools/packages/api/src/api/util.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6f4084947caf4e50c65bf9b499ace74cba24e90d
--- /dev/null
+++ b/vue-devtools/packages/api/src/api/util.ts
@@ -0,0 +1,5 @@
+export type ID = number | string
+
+export interface WithId {
+ id: ID
+}
diff --git a/vue-devtools/packages/api/src/const.ts b/vue-devtools/packages/api/src/const.ts
new file mode 100644
index 0000000000000000000000000000000000000000..102ad1d026193fffe22a3fdebc3f11df59ffaf40
--- /dev/null
+++ b/vue-devtools/packages/api/src/const.ts
@@ -0,0 +1,2 @@
+export const HOOK_SETUP = 'devtools-plugin:setup'
+export const HOOK_PLUGIN_SETTINGS_SET = 'plugin:settings:set'
diff --git a/vue-devtools/packages/api/src/env.ts b/vue-devtools/packages/api/src/env.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f5916ed2f277874d5601dafe2b941ffc982a057f
--- /dev/null
+++ b/vue-devtools/packages/api/src/env.ts
@@ -0,0 +1,28 @@
+import type { ApiProxy } from './proxy.js'
+import type { PluginDescriptor, SetupFunction } from './index.js'
+
+export interface PluginQueueItem {
+ pluginDescriptor: PluginDescriptor
+ setupFn: SetupFunction
+ proxy?: ApiProxy
+}
+
+interface GlobalTarget {
+ __VUE_DEVTOOLS_PLUGINS__?: PluginQueueItem[]
+ __VUE_DEVTOOLS_PLUGIN_API_AVAILABLE__?: boolean
+}
+
+export function getDevtoolsGlobalHook(): any {
+ return (getTarget() as any).__VUE_DEVTOOLS_GLOBAL_HOOK__
+}
+
+export function getTarget(): GlobalTarget {
+ // @ts-expect-error navigator and windows are not available in all environments
+ return (typeof navigator !== 'undefined' && typeof window !== 'undefined')
+ ? window
+ : typeof globalThis !== 'undefined'
+ ? globalThis
+ : {}
+}
+
+export const isProxyAvailable = typeof Proxy === 'function'
diff --git a/vue-devtools/packages/api/src/index.ts b/vue-devtools/packages/api/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c929458de98c4e1abaf50d9f33ace77b06db6155
--- /dev/null
+++ b/vue-devtools/packages/api/src/index.ts
@@ -0,0 +1,56 @@
+import { getDevtoolsGlobalHook, getTarget, isProxyAvailable } from './env.js'
+import { HOOK_SETUP } from './const.js'
+import type { DevtoolsPluginApi } from './api/index.js'
+import { ApiProxy } from './proxy.js'
+import type { ExtractSettingsTypes, PluginDescriptor, PluginSettingsItem } from './plugin.js'
+
+export * from './api/index.js'
+export * from './plugin.js'
+export * from './time.js'
+export { PluginQueueItem } from './env.js'
+
+// https://github.com/microsoft/TypeScript/issues/30680#issuecomment-752725353
+type Cast = A extends B ? A : B
+type Narrowable =
+ | string
+ | number
+ | bigint
+ | boolean
+type Narrow = Cast })>
+
+// Prevent properties not in PluginDescriptor
+// We need this because of the `extends` in the generic TDescriptor
+type Exact = {
+ [K in keyof C]: K extends keyof T ? T[K] : never
+}
+
+export type SetupFunction = (api: DevtoolsPluginApi) => void
+
+export function setupDevtoolsPlugin<
+ TDescriptor extends Exact,
+ TSettings = ExtractSettingsTypes ? S : Record : Record>,
+>(pluginDescriptor: Narrow, setupFn: SetupFunction) {
+ const descriptor = pluginDescriptor as unknown as PluginDescriptor
+ const target = getTarget()
+ const hook = getDevtoolsGlobalHook()
+ const enableProxy = isProxyAvailable && descriptor.enableEarlyProxy
+ if (hook && (target.__VUE_DEVTOOLS_PLUGIN_API_AVAILABLE__ || !enableProxy)) {
+ hook.emit(HOOK_SETUP, pluginDescriptor, setupFn)
+ }
+ else {
+ const proxy = enableProxy ? new ApiProxy(descriptor, hook) : null
+
+ const list = target.__VUE_DEVTOOLS_PLUGINS__ = target.__VUE_DEVTOOLS_PLUGINS__ || []
+ list.push({
+ pluginDescriptor: descriptor,
+ setupFn,
+ proxy,
+ })
+
+ if (proxy) {
+ setupFn(proxy.proxiedTarget as DevtoolsPluginApi)
+ }
+ }
+}
diff --git a/vue-devtools/packages/api/src/plugin.ts b/vue-devtools/packages/api/src/plugin.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f0871879361a5c7a85d2163c0db61ea89d6d2ab8
--- /dev/null
+++ b/vue-devtools/packages/api/src/plugin.ts
@@ -0,0 +1,51 @@
+import type { App } from './api/index.js'
+
+export interface PluginDescriptor {
+ id: string
+ label: string
+ app: App
+ packageName?: string
+ homepage?: string
+ componentStateTypes?: string[]
+ logo?: string
+ disableAppScope?: boolean
+ disablePluginScope?: boolean
+ /**
+ * Run the plugin setup and expose the api even if the devtools is not opened yet.
+ * Useful to record timeline events early.
+ */
+ enableEarlyProxy?: boolean
+ settings?: Record
+}
+
+export type PluginSettingsItem = {
+ label: string
+ description?: string
+} & ({
+ type: 'boolean'
+ defaultValue: boolean
+} | {
+ type: 'choice'
+ defaultValue: string | number
+ options: { value: string | number, label: string }[]
+ component?: 'select' | 'button-group'
+} | {
+ type: 'text'
+ defaultValue: string
+})
+
+type InferSettingsType<
+ T extends PluginSettingsItem,
+> = [T] extends [{ type: 'boolean' }]
+ ? boolean
+ : [T] extends [{ type: 'choice' }]
+ ? T['options'][number]['value']
+ : [T] extends [{ type: 'text' }]
+ ? string
+ : unknown
+
+export type ExtractSettingsTypes<
+ O extends Record,
+> = {
+ [K in keyof O]: InferSettingsType
+}
diff --git a/vue-devtools/packages/api/src/proxy.ts b/vue-devtools/packages/api/src/proxy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1727060323e81bb233766e92b6cafb42074c79f7
--- /dev/null
+++ b/vue-devtools/packages/api/src/proxy.ts
@@ -0,0 +1,136 @@
+import type { Context, DevtoolsPluginApi, Hookable } from './api/index.js'
+import type { PluginDescriptor } from './plugin.js'
+import { HOOK_PLUGIN_SETTINGS_SET } from './const.js'
+import { now } from './time.js'
+
+interface QueueItem {
+ method: string
+ args: any[]
+ resolve?: (value?: any) => void
+}
+
+export class ApiProxy = DevtoolsPluginApi> {
+ target: TTarget | null
+ targetQueue: QueueItem[]
+ proxiedTarget: TTarget
+
+ onQueue: QueueItem[]
+ proxiedOn: Hookable
+
+ plugin: PluginDescriptor
+ hook: any
+ fallbacks: Record
+
+ constructor(plugin: PluginDescriptor, hook: any) {
+ this.target = null
+ this.targetQueue = []
+ this.onQueue = []
+
+ this.plugin = plugin
+ this.hook = hook
+
+ const defaultSettings: Record = {}
+ if (plugin.settings) {
+ for (const id in plugin.settings) {
+ const item = plugin.settings[id]
+ defaultSettings[id] = item.defaultValue
+ }
+ }
+ const localSettingsSaveId = `__vue-devtools-plugin-settings__${plugin.id}`
+ let currentSettings = Object.assign({}, defaultSettings)
+ try {
+ const raw = localStorage.getItem(localSettingsSaveId)
+ const data = JSON.parse(raw)
+ Object.assign(currentSettings, data)
+ }
+ catch (e) {
+ // noop
+ }
+
+ this.fallbacks = {
+ getSettings() {
+ return currentSettings
+ },
+ setSettings(value) {
+ try {
+ localStorage.setItem(localSettingsSaveId, JSON.stringify(value))
+ }
+ catch (e) {
+ // noop
+ }
+ currentSettings = value
+ },
+ now() {
+ return now()
+ },
+ }
+
+ if (hook) {
+ hook.on(HOOK_PLUGIN_SETTINGS_SET, (pluginId, value) => {
+ if (pluginId === this.plugin.id) {
+ this.fallbacks.setSettings(value)
+ }
+ })
+ }
+
+ this.proxiedOn = new Proxy({} as Hookable, {
+ get: (_target, prop: string) => {
+ if (this.target) {
+ return this.target.on[prop]
+ }
+ else {
+ return (...args) => {
+ this.onQueue.push({
+ method: prop,
+ args,
+ })
+ }
+ }
+ },
+ })
+
+ this.proxiedTarget = new Proxy({} as TTarget, {
+ get: (_target, prop: string) => {
+ if (this.target) {
+ return this.target[prop]
+ }
+ else if (prop === 'on') {
+ return this.proxiedOn
+ }
+ else if (Object.keys(this.fallbacks).includes(prop)) {
+ return (...args) => {
+ this.targetQueue.push({
+ method: prop,
+ args,
+ resolve: () => { /* noop */ },
+ })
+ return this.fallbacks[prop](...args)
+ }
+ }
+ else {
+ return (...args) => {
+ return new Promise((resolve) => {
+ this.targetQueue.push({
+ method: prop,
+ args,
+ resolve,
+ })
+ })
+ }
+ }
+ },
+ })
+ }
+
+ async setRealTarget(target: TTarget) {
+ this.target = target
+
+ for (const item of this.onQueue) {
+ this.target.on[item.method](...item.args)
+ }
+
+ for (const item of this.targetQueue) {
+ item.resolve(await this.target[item.method](...item.args))
+ }
+ }
+}
diff --git a/vue-devtools/packages/api/src/time.ts b/vue-devtools/packages/api/src/time.ts
new file mode 100644
index 0000000000000000000000000000000000000000..87f919c6bb35d60a3e7fe2f012fa06ee207073be
--- /dev/null
+++ b/vue-devtools/packages/api/src/time.ts
@@ -0,0 +1,24 @@
+let supported: boolean
+let perf: Performance
+
+export function isPerformanceSupported() {
+ if (supported !== undefined) {
+ return supported
+ }
+ if (typeof window !== 'undefined' && window.performance) {
+ supported = true
+ perf = window.performance
+ }
+ else if (typeof globalThis !== 'undefined' && (globalThis as any).perf_hooks?.performance) {
+ supported = true
+ perf = (globalThis as any).perf_hooks.performance
+ }
+ else {
+ supported = false
+ }
+ return supported
+}
+
+export function now() {
+ return isPerformanceSupported() ? perf.now() : Date.now()
+}
diff --git a/vue-devtools/packages/api/tsconfig.json b/vue-devtools/packages/api/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..51b26605431a259a65a3c1722acf31891350a5e4
--- /dev/null
+++ b/vue-devtools/packages/api/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "compilerOptions": {
+ "target": "ES2017",
+ "lib": ["ESNext", "DOM"],
+ "module": "ESNext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "types": ["node", "webpack-env"],
+ "strictBindCallApply": true,
+ "strictFunctionTypes": true,
+ "alwaysStrict": true,
+ // Strict
+ "noImplicitAny": false,
+ "noImplicitThis": true,
+ "removeComments": false,
+ "sourceMap": false,
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "preserveWatchOutput": true
+ },
+ "include": ["src/**/*"],
+ "exclude": ["node_modules"]
+}
diff --git a/vue-devtools/packages/app-backend-api/package.json b/vue-devtools/packages/app-backend-api/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..a271ec9312ae7f863615ca757e61d0b75c9b7c83
--- /dev/null
+++ b/vue-devtools/packages/app-backend-api/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "@vue-devtools/app-backend-api",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./lib/index.js",
+ "types": "./lib/index.d.ts",
+ "scripts": {
+ "build": "rimraf lib && yarn ts",
+ "build:watch": "yarn ts -w",
+ "ts": "tsc -d -outDir lib"
+ },
+ "dependencies": {
+ "@vue-devtools/shared-utils": "^0.0.0",
+ "@vue/devtools-api": "^6.0.0-beta.1"
+ },
+ "devDependencies": {
+ "@types/node": "^20.11.16",
+ "@types/webpack-env": "^1.15.1",
+ "typescript": "^5.3.3"
+ }
+}
diff --git a/vue-devtools/packages/app-backend-api/src/api.ts b/vue-devtools/packages/app-backend-api/src/api.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c08f96cd23b59301882e25245b779bdc03799905
--- /dev/null
+++ b/vue-devtools/packages/app-backend-api/src/api.ts
@@ -0,0 +1,398 @@
+import type {
+ Bridge,
+} from '@vue-devtools/shared-utils'
+import {
+ HookEvents,
+ PluginPermission,
+ StateEditor,
+ getPluginDefaultSettings,
+ getPluginSettings,
+ hasPluginPermission,
+ setPluginSettings,
+} from '@vue-devtools/shared-utils'
+import type {
+ App,
+ ComponentDevtoolsOptions,
+ ComponentInstance,
+ ComponentTreeNode,
+ CustomInspectorOptions,
+ DevtoolsPluginApi,
+ EditStatePayload,
+ HookPayloads,
+ TimelineEventOptions,
+ TimelineLayerOptions,
+ WithId,
+} from '@vue/devtools-api'
+import {
+ Hooks,
+ now,
+} from '@vue/devtools-api'
+import { DevtoolsHookable } from './hooks'
+import type { BackendContext } from './backend-context'
+import type { Plugin } from './plugin'
+import type { DevtoolsBackend } from './backend'
+import type { AppRecord } from './app-record'
+
+const pluginOn: DevtoolsHookable[] = []
+
+export class DevtoolsApi {
+ bridge: Bridge
+ ctx: BackendContext
+ backend: DevtoolsBackend
+ on: DevtoolsHookable
+ stateEditor: StateEditor = new StateEditor()
+
+ constructor(backend: DevtoolsBackend, ctx: BackendContext) {
+ this.backend = backend
+ this.ctx = ctx
+ this.bridge = ctx.bridge
+ this.on = new DevtoolsHookable(ctx)
+ }
+
+ async callHook(eventType: T, payload: HookPayloads[T], ctx: BackendContext = this.ctx) {
+ payload = await this.on.callHandlers(eventType, payload, ctx)
+ for (const on of pluginOn) {
+ payload = await on.callHandlers(eventType, payload, ctx)
+ }
+ return payload
+ }
+
+ async transformCall(callName: string, ...args) {
+ const payload = await this.callHook(Hooks.TRANSFORM_CALL, {
+ callName,
+ inArgs: args,
+ outArgs: args.slice(),
+ })
+ return payload.outArgs
+ }
+
+ async getAppRecordName(app: App, defaultName: string): Promise {
+ const payload = await this.callHook(Hooks.GET_APP_RECORD_NAME, {
+ app,
+ name: null,
+ })
+ if (payload.name) {
+ return payload.name
+ }
+ else {
+ return `App ${defaultName}`
+ }
+ }
+
+ async getAppRootInstance(app: App) {
+ const payload = await this.callHook(Hooks.GET_APP_ROOT_INSTANCE, {
+ app,
+ root: null,
+ })
+ return payload.root
+ }
+
+ async registerApplication(app: App) {
+ await this.callHook(Hooks.REGISTER_APPLICATION, {
+ app,
+ })
+ }
+
+ async walkComponentTree(instance: ComponentInstance, maxDepth = -1, filter: string = null, recursively = false) {
+ const payload = await this.callHook(Hooks.WALK_COMPONENT_TREE, {
+ componentInstance: instance,
+ componentTreeData: null,
+ maxDepth,
+ filter,
+ recursively,
+ })
+ return payload.componentTreeData
+ }
+
+ async visitComponentTree(instance: ComponentInstance, treeNode: ComponentTreeNode, filter: string = null, app: App) {
+ const payload = await this.callHook(Hooks.VISIT_COMPONENT_TREE, {
+ app,
+ componentInstance: instance,
+ treeNode,
+ filter,
+ })
+ return payload.treeNode
+ }
+
+ async walkComponentParents(instance: ComponentInstance) {
+ const payload = await this.callHook(Hooks.WALK_COMPONENT_PARENTS, {
+ componentInstance: instance,
+ parentInstances: [],
+ })
+ return payload.parentInstances
+ }
+
+ async inspectComponent(instance: ComponentInstance, app: App) {
+ const payload = await this.callHook(Hooks.INSPECT_COMPONENT, {
+ app,
+ componentInstance: instance,
+ instanceData: null,
+ })
+ return payload.instanceData
+ }
+
+ async getComponentBounds(instance: ComponentInstance) {
+ const payload = await this.callHook(Hooks.GET_COMPONENT_BOUNDS, {
+ componentInstance: instance,
+ bounds: null,
+ })
+ return payload.bounds
+ }
+
+ async getComponentName(instance: ComponentInstance) {
+ const payload = await this.callHook(Hooks.GET_COMPONENT_NAME, {
+ componentInstance: instance,
+ name: null,
+ })
+ return payload.name
+ }
+
+ async getComponentInstances(app: App) {
+ const payload = await this.callHook(Hooks.GET_COMPONENT_INSTANCES, {
+ app,
+ componentInstances: [],
+ })
+ return payload.componentInstances
+ }
+
+ async getElementComponent(element: HTMLElement | any) {
+ const payload = await this.callHook(Hooks.GET_ELEMENT_COMPONENT, {
+ element,
+ componentInstance: null,
+ })
+ return payload.componentInstance
+ }
+
+ async getComponentRootElements(instance: ComponentInstance) {
+ const payload = await this.callHook(Hooks.GET_COMPONENT_ROOT_ELEMENTS, {
+ componentInstance: instance,
+ rootElements: [],
+ })
+ return payload.rootElements
+ }
+
+ async editComponentState(instance: ComponentInstance, dotPath: string, type: string, state: EditStatePayload, app: App) {
+ const arrayPath = dotPath.split('.')
+ const payload = await this.callHook(Hooks.EDIT_COMPONENT_STATE, {
+ app,
+ componentInstance: instance,
+ path: arrayPath,
+ type,
+ state,
+ set: (object, path = arrayPath, value = state.value, cb?) => this.stateEditor.set(object, path, value, cb || this.stateEditor.createDefaultSetCallback(state)),
+ })
+ return payload.componentInstance
+ }
+
+ async getComponentDevtoolsOptions(instance: ComponentInstance): Promise {
+ const payload = await this.callHook(Hooks.GET_COMPONENT_DEVTOOLS_OPTIONS, {
+ componentInstance: instance,
+ options: null,
+ })
+ return payload.options || {}
+ }
+
+ async getComponentRenderCode(instance: ComponentInstance): Promise<{
+ code: string
+ }> {
+ const payload = await this.callHook(Hooks.GET_COMPONENT_RENDER_CODE, {
+ componentInstance: instance,
+ code: null,
+ })
+ return {
+ code: payload.code,
+ }
+ }
+
+ async inspectTimelineEvent(eventData: TimelineEventOptions & WithId, app: App) {
+ const payload = await this.callHook(Hooks.INSPECT_TIMELINE_EVENT, {
+ event: eventData.event,
+ layerId: eventData.layerId,
+ app,
+ data: eventData.event.data,
+ all: eventData.all,
+ })
+ return payload.data
+ }
+
+ async clearTimeline() {
+ await this.callHook(Hooks.TIMELINE_CLEARED, {})
+ }
+
+ async getInspectorTree(inspectorId: string, app: App, filter: string) {
+ const payload = await this.callHook(Hooks.GET_INSPECTOR_TREE, {
+ inspectorId,
+ app,
+ filter,
+ rootNodes: [],
+ })
+ return payload.rootNodes
+ }
+
+ async getInspectorState(inspectorId: string, app: App, nodeId: string) {
+ const payload = await this.callHook(Hooks.GET_INSPECTOR_STATE, {
+ inspectorId,
+ app,
+ nodeId,
+ state: null,
+ })
+ return payload.state
+ }
+
+ async editInspectorState(inspectorId: string, app: App, nodeId: string, dotPath: string, type: string, state: EditStatePayload) {
+ const arrayPath = dotPath.split('.')
+ await this.callHook(Hooks.EDIT_INSPECTOR_STATE, {
+ inspectorId,
+ app,
+ nodeId,
+ path: arrayPath,
+ type,
+ state,
+ set: (object, path = arrayPath, value = state.value, cb?) => this.stateEditor.set(object, path, value, cb || this.stateEditor.createDefaultSetCallback(state)),
+ })
+ }
+
+ now() {
+ return now()
+ }
+}
+
+export class DevtoolsPluginApiInstance implements DevtoolsPluginApi {
+ bridge: Bridge
+ ctx: BackendContext
+ plugin: Plugin
+ appRecord: AppRecord
+ backendApi: DevtoolsApi
+ on: DevtoolsHookable
+ private defaultSettings: TSettings
+
+ constructor(plugin: Plugin, appRecord: AppRecord, ctx: BackendContext) {
+ this.bridge = ctx.bridge
+ this.ctx = ctx
+ this.plugin = plugin
+ this.appRecord = appRecord
+ this.backendApi = appRecord.backend.api
+ this.defaultSettings = getPluginDefaultSettings(plugin.descriptor.settings)
+ this.on = new DevtoolsHookable(ctx, plugin)
+ pluginOn.push(this.on)
+ }
+
+ // Plugin API
+
+ async notifyComponentUpdate(instance: ComponentInstance = null) {
+ if (!this.enabled || !this.hasPermission(PluginPermission.COMPONENTS)) {
+ return
+ }
+
+ if (instance) {
+ this.ctx.hook.emit(HookEvents.COMPONENT_UPDATED, ...await this.backendApi.transformCall(HookEvents.COMPONENT_UPDATED, instance))
+ }
+ else {
+ this.ctx.hook.emit(HookEvents.COMPONENT_UPDATED)
+ }
+ }
+
+ addTimelineLayer(options: TimelineLayerOptions) {
+ if (!this.enabled || !this.hasPermission(PluginPermission.TIMELINE)) {
+ return false
+ }
+
+ this.ctx.hook.emit(HookEvents.TIMELINE_LAYER_ADDED, options, this.plugin)
+ return true
+ }
+
+ addTimelineEvent(options: TimelineEventOptions) {
+ if (!this.enabled || !this.hasPermission(PluginPermission.TIMELINE)) {
+ return false
+ }
+
+ this.ctx.hook.emit(HookEvents.TIMELINE_EVENT_ADDED, options, this.plugin)
+ return true
+ }
+
+ addInspector(options: CustomInspectorOptions) {
+ if (!this.enabled || !this.hasPermission(PluginPermission.CUSTOM_INSPECTOR)) {
+ return false
+ }
+
+ this.ctx.hook.emit(HookEvents.CUSTOM_INSPECTOR_ADD, options, this.plugin)
+ return true
+ }
+
+ sendInspectorTree(inspectorId: string) {
+ if (!this.enabled || !this.hasPermission(PluginPermission.CUSTOM_INSPECTOR)) {
+ return false
+ }
+
+ this.ctx.hook.emit(HookEvents.CUSTOM_INSPECTOR_SEND_TREE, inspectorId, this.plugin)
+ return true
+ }
+
+ sendInspectorState(inspectorId: string) {
+ if (!this.enabled || !this.hasPermission(PluginPermission.CUSTOM_INSPECTOR)) {
+ return false
+ }
+
+ this.ctx.hook.emit(HookEvents.CUSTOM_INSPECTOR_SEND_STATE, inspectorId, this.plugin)
+ return true
+ }
+
+ selectInspectorNode(inspectorId: string, nodeId: string) {
+ if (!this.enabled || !this.hasPermission(PluginPermission.CUSTOM_INSPECTOR)) {
+ return false
+ }
+
+ this.ctx.hook.emit(HookEvents.CUSTOM_INSPECTOR_SELECT_NODE, inspectorId, nodeId, this.plugin)
+ return true
+ }
+
+ getComponentBounds(instance: ComponentInstance) {
+ return this.backendApi.getComponentBounds(instance)
+ }
+
+ getComponentName(instance: ComponentInstance) {
+ return this.backendApi.getComponentName(instance)
+ }
+
+ getComponentInstances(app: App) {
+ return this.backendApi.getComponentInstances(app)
+ }
+
+ highlightElement(instance: ComponentInstance) {
+ if (!this.enabled || !this.hasPermission(PluginPermission.COMPONENTS)) {
+ return false
+ }
+
+ this.ctx.hook.emit(HookEvents.COMPONENT_HIGHLIGHT, instance.__VUE_DEVTOOLS_UID__, this.plugin)
+ return true
+ }
+
+ unhighlightElement() {
+ if (!this.enabled || !this.hasPermission(PluginPermission.COMPONENTS)) {
+ return false
+ }
+
+ this.ctx.hook.emit(HookEvents.COMPONENT_UNHIGHLIGHT, this.plugin)
+ return true
+ }
+
+ getSettings(pluginId?: string) {
+ return getPluginSettings(pluginId ?? this.plugin.descriptor.id, this.defaultSettings)
+ }
+
+ setSettings(value: TSettings, pluginId?: string) {
+ setPluginSettings(pluginId ?? this.plugin.descriptor.id, value)
+ }
+
+ now() {
+ return now()
+ }
+
+ private get enabled() {
+ return hasPluginPermission(this.plugin.descriptor.id, PluginPermission.ENABLED)
+ }
+
+ private hasPermission(permission: PluginPermission) {
+ return hasPluginPermission(this.plugin.descriptor.id, permission)
+ }
+}
diff --git a/vue-devtools/packages/app-backend-api/src/app-record.ts b/vue-devtools/packages/app-backend-api/src/app-record.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8aad57d040be55bbe23abe62b9ca1db3ea5e0813
--- /dev/null
+++ b/vue-devtools/packages/app-backend-api/src/app-record.ts
@@ -0,0 +1,34 @@
+import type { App, ComponentInstance } from '@vue/devtools-api'
+import type { DevtoolsBackend } from './backend'
+
+export interface AppRecordOptions {
+ app: App
+ version: string
+ types: { [key: string]: string | symbol }
+ meta?: any
+}
+
+export interface AppRecord {
+ id: string
+ name: string
+ options: AppRecordOptions
+ backend: DevtoolsBackend
+ lastInspectedComponentId: string
+ instanceMap: Map
+ rootInstance: ComponentInstance
+ componentFilter?: string
+ perfGroupIds: Map
+ iframe: string
+ meta: any
+ missingInstanceQueue: Set
+}
+
+/**
+ * Used in the frontend
+ */
+export interface SimpleAppRecord {
+ id: string
+ name: string
+ version: string
+ iframe: string
+}
diff --git a/vue-devtools/packages/app-backend-api/src/backend-context.ts b/vue-devtools/packages/app-backend-api/src/backend-context.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d878ec0631eae240af7ecb9a359d6796fe41a6ea
--- /dev/null
+++ b/vue-devtools/packages/app-backend-api/src/backend-context.ts
@@ -0,0 +1,73 @@
+import type { Bridge } from '@vue-devtools/shared-utils'
+import type {
+ CustomInspectorOptions,
+ ID,
+ TimelineEventOptions,
+ TimelineLayerOptions,
+ TimelineMarkerOptions,
+ WithId,
+} from '@vue/devtools-api'
+import type { AppRecord } from './app-record'
+import type { Plugin } from './plugin'
+import type { DevtoolsHook } from './global-hook'
+import type { DevtoolsBackend } from './backend'
+
+export interface BackendContext {
+ bridge: Bridge
+ hook: DevtoolsHook
+ backends: DevtoolsBackend[]
+ appRecords: AppRecord[]
+ currentTab: string
+ currentAppRecord: AppRecord
+ currentInspectedComponentId: string
+ plugins: Plugin[]
+ currentPlugin: Plugin
+ timelineLayers: TimelineLayer[]
+ nextTimelineEventId: number
+ timelineEventMap: Map
+ perfUniqueGroupId: number
+ customInspectors: CustomInspector[]
+ timelineMarkers: TimelineMarker[]
+}
+
+export interface TimelineLayer extends TimelineLayerOptions {
+ appRecord: AppRecord | null
+ plugin: Plugin
+ events: (TimelineEventOptions & WithId)[]
+}
+
+export interface TimelineMarker extends TimelineMarkerOptions {
+ appRecord: AppRecord | null
+}
+
+export interface CustomInspector extends CustomInspectorOptions {
+ appRecord: AppRecord
+ plugin: Plugin
+ treeFilter: string
+ selectedNodeId: string
+}
+
+export interface CreateBackendContextOptions {
+ bridge: Bridge
+ hook: DevtoolsHook
+}
+
+export function createBackendContext(options: CreateBackendContextOptions): BackendContext {
+ return {
+ bridge: options.bridge,
+ hook: options.hook,
+ backends: [],
+ appRecords: [],
+ currentTab: null,
+ currentAppRecord: null,
+ currentInspectedComponentId: null,
+ plugins: [],
+ currentPlugin: null,
+ timelineLayers: [],
+ nextTimelineEventId: 0,
+ timelineEventMap: new Map(),
+ perfUniqueGroupId: 0,
+ customInspectors: [],
+ timelineMarkers: [],
+ }
+}
diff --git a/vue-devtools/packages/app-backend-api/src/backend.ts b/vue-devtools/packages/app-backend-api/src/backend.ts
new file mode 100644
index 0000000000000000000000000000000000000000..67e4975afe0d0b377a1e9e486739f7e3198dfa33
--- /dev/null
+++ b/vue-devtools/packages/app-backend-api/src/backend.ts
@@ -0,0 +1,36 @@
+import type { AppRecord } from './app-record'
+import { DevtoolsApi } from './api'
+import type { BackendContext } from './backend-context'
+
+export enum BuiltinBackendFeature {
+ /**
+ * @deprecated
+ */
+ FLUSH = 'flush',
+}
+
+export interface DevtoolsBackendOptions {
+ frameworkVersion: 1 | 2 | 3
+ features: (BuiltinBackendFeature | string)[]
+ setup: (api: DevtoolsApi) => void
+ setupApp?: (api: DevtoolsApi, app: AppRecord) => void
+}
+
+export function defineBackend(options: DevtoolsBackendOptions) {
+ return options
+}
+
+export interface DevtoolsBackend {
+ options: DevtoolsBackendOptions
+ api: DevtoolsApi
+}
+
+export function createBackend(options: DevtoolsBackendOptions, ctx: BackendContext): DevtoolsBackend {
+ const backend: DevtoolsBackend = {
+ options,
+ api: null,
+ }
+ backend.api = new DevtoolsApi(backend, ctx)
+ options.setup(backend.api)
+ return backend
+}
diff --git a/vue-devtools/packages/app-backend-api/src/global-hook.ts b/vue-devtools/packages/app-backend-api/src/global-hook.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5c07e85c55f4c7b9f7a484ea9e64c9ef83520fdd
--- /dev/null
+++ b/vue-devtools/packages/app-backend-api/src/global-hook.ts
@@ -0,0 +1,10 @@
+import type { AppRecordOptions } from './app-record'
+
+export interface DevtoolsHook {
+ emit: (event: string, ...payload: any[]) => void
+ on: (event: string, handler: T) => void
+ once: (event: string, handler: T) => void
+ off: (event?: string, handler?: T) => void
+ Vue?: any
+ apps: AppRecordOptions[]
+}
diff --git a/vue-devtools/packages/app-backend-api/src/hooks.ts b/vue-devtools/packages/app-backend-api/src/hooks.ts
new file mode 100644
index 0000000000000000000000000000000000000000..febecc222ac457e50a262f127459ab4a4b3cf19e
--- /dev/null
+++ b/vue-devtools/packages/app-backend-api/src/hooks.ts
@@ -0,0 +1,159 @@
+import { PluginPermission, SharedData, hasPluginPermission } from '@vue-devtools/shared-utils'
+import type { HookHandler, HookPayloads, Hookable } from '@vue/devtools-api'
+import { Hooks } from '@vue/devtools-api'
+import type { BackendContext } from './backend-context'
+import type { Plugin } from './plugin'
+
+type Handler = HookHandler
+
+export interface HookHandlerData {
+ handler: Handler
+ plugin: Plugin
+}
+
+export class DevtoolsHookable implements Hookable {
+ private handlers: Partial<{ [eventType in Hooks]: HookHandlerData[] }> = {}
+ private ctx: BackendContext
+ private plugin: Plugin
+
+ constructor(ctx: BackendContext, plugin: Plugin = null) {
+ this.ctx = ctx
+ this.plugin = plugin
+ }
+
+ private hook(eventType: T, handler: Handler, pluginPermision: PluginPermission = null) {
+ const handlers = (this.handlers[eventType] = this.handlers[eventType] || []) as HookHandlerData[]
+
+ if (this.plugin) {
+ const originalHandler = handler
+ handler = (...args) => {
+ // Plugin permission
+ if (!hasPluginPermission(this.plugin.descriptor.id, PluginPermission.ENABLED)
+ || (pluginPermision && !hasPluginPermission(this.plugin.descriptor.id, pluginPermision))
+ ) { return }
+
+ // App scope
+ if (!this.plugin.descriptor.disableAppScope
+ && this.ctx.currentAppRecord?.options.app !== this.plugin.descriptor.app) { return }
+
+ // Plugin scope
+ if (!this.plugin.descriptor.disablePluginScope
+ && (args[0] as any).pluginId != null && (args[0] as any).pluginId !== this.plugin.descriptor.id) { return }
+
+ return originalHandler(...args)
+ }
+ }
+
+ handlers.push({
+ handler,
+ plugin: this.ctx.currentPlugin,
+ })
+ }
+
+ async callHandlers(eventType: T, payload: HookPayloads[T], ctx: BackendContext) {
+ if (this.handlers[eventType]) {
+ const handlers = this.handlers[eventType] as HookHandlerData[]
+ for (let i = 0; i < handlers.length; i++) {
+ const { handler, plugin } = handlers[i]
+ try {
+ await handler(payload, ctx)
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(`An error occurred in hook '${eventType}'${plugin ? ` registered by plugin '${plugin.descriptor.id}'` : ''} with payload:`, payload)
+ console.error(e)
+ }
+ }
+ }
+ }
+ return payload
+ }
+
+ transformCall(handler: Handler) {
+ this.hook(Hooks.TRANSFORM_CALL, handler)
+ }
+
+ getAppRecordName(handler: Handler) {
+ this.hook(Hooks.GET_APP_RECORD_NAME, handler)
+ }
+
+ getAppRootInstance(handler: Handler) {
+ this.hook(Hooks.GET_APP_ROOT_INSTANCE, handler)
+ }
+
+ registerApplication(handler: Handler) {
+ this.hook(Hooks.REGISTER_APPLICATION, handler)
+ }
+
+ walkComponentTree(handler: Handler) {
+ this.hook(Hooks.WALK_COMPONENT_TREE, handler, PluginPermission.COMPONENTS)
+ }
+
+ visitComponentTree(handler: Handler) {
+ this.hook(Hooks.VISIT_COMPONENT_TREE, handler, PluginPermission.COMPONENTS)
+ }
+
+ walkComponentParents(handler: Handler) {
+ this.hook(Hooks.WALK_COMPONENT_PARENTS, handler, PluginPermission.COMPONENTS)
+ }
+
+ inspectComponent(handler: Handler) {
+ this.hook(Hooks.INSPECT_COMPONENT, handler, PluginPermission.COMPONENTS)
+ }
+
+ getComponentBounds(handler: Handler) {
+ this.hook(Hooks.GET_COMPONENT_BOUNDS, handler, PluginPermission.COMPONENTS)
+ }
+
+ getComponentName(handler: Handler) {
+ this.hook(Hooks.GET_COMPONENT_NAME, handler, PluginPermission.COMPONENTS)
+ }
+
+ getComponentInstances(handler: Handler) {
+ this.hook(Hooks.GET_COMPONENT_INSTANCES, handler, PluginPermission.COMPONENTS)
+ }
+
+ getElementComponent(handler: Handler) {
+ this.hook(Hooks.GET_ELEMENT_COMPONENT, handler, PluginPermission.COMPONENTS)
+ }
+
+ getComponentRootElements(handler: Handler) {
+ this.hook(Hooks.GET_COMPONENT_ROOT_ELEMENTS, handler, PluginPermission.COMPONENTS)
+ }
+
+ editComponentState(handler: Handler) {
+ this.hook(Hooks.EDIT_COMPONENT_STATE, handler, PluginPermission.COMPONENTS)
+ }
+
+ getComponentDevtoolsOptions(handler: Handler) {
+ this.hook(Hooks.GET_COMPONENT_DEVTOOLS_OPTIONS, handler, PluginPermission.COMPONENTS)
+ }
+
+ getComponentRenderCode(handler: Handler) {
+ this.hook(Hooks.GET_COMPONENT_RENDER_CODE, handler, PluginPermission.COMPONENTS)
+ }
+
+ inspectTimelineEvent(handler: Handler) {
+ this.hook(Hooks.INSPECT_TIMELINE_EVENT, handler, PluginPermission.TIMELINE)
+ }
+
+ timelineCleared(handler: Handler) {
+ this.hook(Hooks.TIMELINE_CLEARED, handler, PluginPermission.TIMELINE)
+ }
+
+ getInspectorTree(handler: Handler) {
+ this.hook(Hooks.GET_INSPECTOR_TREE, handler, PluginPermission.CUSTOM_INSPECTOR)
+ }
+
+ getInspectorState(handler: Handler) {
+ this.hook(Hooks.GET_INSPECTOR_STATE, handler, PluginPermission.CUSTOM_INSPECTOR)
+ }
+
+ editInspectorState(handler: Handler) {
+ this.hook(Hooks.EDIT_INSPECTOR_STATE, handler, PluginPermission.CUSTOM_INSPECTOR)
+ }
+
+ setPluginSettings(handler: Handler) {
+ this.hook(Hooks.SET_PLUGIN_SETTINGS, handler)
+ }
+}
diff --git a/vue-devtools/packages/app-backend-api/src/index.ts b/vue-devtools/packages/app-backend-api/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5e0448cd5891779ea6de8695871477fcf8d941e5
--- /dev/null
+++ b/vue-devtools/packages/app-backend-api/src/index.ts
@@ -0,0 +1,7 @@
+export * from './api'
+export * from './app-record'
+export * from './backend'
+export * from './backend-context'
+export * from './global-hook'
+export * from './hooks'
+export * from './plugin'
diff --git a/vue-devtools/packages/app-backend-api/src/plugin.ts b/vue-devtools/packages/app-backend-api/src/plugin.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f9df976c130b02e0ca7a20a9a6e13c0c24418bde
--- /dev/null
+++ b/vue-devtools/packages/app-backend-api/src/plugin.ts
@@ -0,0 +1,7 @@
+import type { PluginDescriptor, SetupFunction } from '@vue/devtools-api'
+
+export interface Plugin {
+ descriptor: PluginDescriptor
+ setupFn: SetupFunction
+ error: Error
+}
diff --git a/vue-devtools/packages/app-backend-api/tsconfig.json b/vue-devtools/packages/app-backend-api/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..becb763b20bbbd4557ba0717c957b4e3d3d6c81b
--- /dev/null
+++ b/vue-devtools/packages/app-backend-api/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "target": "ES2019",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "types": [
+ "node",
+ "webpack-env"
+ ],
+ "strictBindCallApply": true,
+ "strictFunctionTypes": true,
+ "alwaysStrict": true,
+ // Strict
+ "noImplicitAny": false,
+ "noImplicitThis": true,
+ "sourceMap": true,
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "preserveWatchOutput": true
+ },
+ "include": [
+ "src/**/*"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/vue-devtools/packages/app-backend-core/package.json b/vue-devtools/packages/app-backend-core/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..4249524c3b1e79b1d8e1123e32c95ac1ff724907
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "@vue-devtools/app-backend-core",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./lib/index.js",
+ "types": "./lib/index.d.ts",
+ "scripts": {
+ "build": "rimraf lib && yarn ts",
+ "build:watch": "yarn ts -w",
+ "ts": "tsc -d -outDir lib"
+ },
+ "dependencies": {
+ "@vue-devtools/app-backend-api": "^0.0.0",
+ "@vue-devtools/app-backend-vue1": "^0.0.0",
+ "@vue-devtools/app-backend-vue2": "^0.0.0",
+ "@vue-devtools/app-backend-vue3": "^0.0.0",
+ "@vue-devtools/shared-utils": "^0.0.0",
+ "@vue/devtools-api": "^6.0.0-beta.1",
+ "lodash": "^4.17.21",
+ "speakingurl": "^14.0.1"
+ },
+ "devDependencies": {
+ "@types/node": "^20.11.16",
+ "@types/webpack-env": "^1.15.1",
+ "typescript": "^5.3.3"
+ }
+}
diff --git a/vue-devtools/packages/app-backend-core/src/app.ts b/vue-devtools/packages/app-backend-core/src/app.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9a43c35560bf5e5c2666cb2cc072954f43f56ddf
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/app.ts
@@ -0,0 +1,304 @@
+import type {
+ AppRecord,
+ AppRecordOptions,
+ BackendContext,
+ DevtoolsBackend,
+ SimpleAppRecord,
+} from '@vue-devtools/app-backend-api'
+import { BridgeEvents, SharedData, isBrowser } from '@vue-devtools/shared-utils'
+import type { App } from '@vue/devtools-api'
+import slug from 'speakingurl'
+import { JobQueue } from './util/queue'
+import { scan } from './legacy/scan'
+import { addBuiltinLayers, removeLayersForApp } from './timeline'
+import { availableBackends, getBackend } from './backend'
+import { hook } from './global-hook.js'
+import { sendComponentTreeData, sendSelectedComponentData } from './component.js'
+
+const jobs = new JobQueue()
+
+let recordId = 0
+
+type AppRecordResolver = (record: AppRecord) => void | Promise
+const appRecordPromises = new Map()
+
+export async function registerApp(options: AppRecordOptions, ctx: BackendContext) {
+ return jobs.queue('regiserApp', () => registerAppJob(options, ctx))
+}
+
+async function registerAppJob(options: AppRecordOptions, ctx: BackendContext) {
+ // Dedupe
+ if (ctx.appRecords.find(a => a.options.app === options.app)) {
+ return
+ }
+
+ if (!options.version) {
+ throw new Error('[Vue Devtools] Vue version not found')
+ }
+
+ // Find correct backend
+ const baseFrameworkVersion = Number.parseInt(options.version.substring(0, options.version.indexOf('.')))
+ for (let i = 0; i < availableBackends.length; i++) {
+ const backendOptions = availableBackends[i]
+ if (backendOptions.frameworkVersion === baseFrameworkVersion) {
+ // Enable backend if it's not enabled
+ const backend = getBackend(backendOptions, ctx)
+
+ await createAppRecord(options, backend, ctx)
+
+ break
+ }
+ }
+}
+
+async function createAppRecord(options: AppRecordOptions, backend: DevtoolsBackend, ctx: BackendContext) {
+ const rootInstance = await backend.api.getAppRootInstance(options.app)
+ if (rootInstance) {
+ if ((await backend.api.getComponentDevtoolsOptions(rootInstance)).hide) {
+ options.app._vueDevtools_hidden_ = true
+ return
+ }
+
+ recordId++
+ const name = await backend.api.getAppRecordName(options.app, recordId.toString())
+ const id = getAppRecordId(options.app, slug(name))
+
+ const [el]: HTMLElement[] = await backend.api.getComponentRootElements(rootInstance)
+
+ const instanceMapRaw = new Map()
+
+ const record: AppRecord = {
+ id,
+ name,
+ options,
+ backend,
+ lastInspectedComponentId: null,
+ instanceMap: new Proxy(instanceMapRaw, {
+ get(target, key: string) {
+ if (key === 'set') {
+ return (instanceId: string, instance: any) => {
+ target.set(instanceId, instance)
+ // The component was requested by the frontend before it was registered
+ if (record.missingInstanceQueue.has(instanceId)) {
+ record.missingInstanceQueue.delete(instanceId)
+ if (ctx.currentAppRecord === record) {
+ sendComponentTreeData(record, instanceId, record.componentFilter, null, false, ctx)
+ if (record.lastInspectedComponentId === instanceId) {
+ sendSelectedComponentData(record, instanceId, ctx)
+ }
+ }
+ }
+ }
+ }
+ return target[key].bind(target)
+ },
+ }),
+ rootInstance,
+ perfGroupIds: new Map(),
+ iframe: isBrowser && document !== el?.ownerDocument ? el?.ownerDocument?.location?.pathname : null,
+ meta: options.meta ?? {},
+ missingInstanceQueue: new Set(),
+ }
+
+ options.app.__VUE_DEVTOOLS_APP_RECORD__ = record
+ const rootId = `${record.id}:root`
+ record.instanceMap.set(rootId, record.rootInstance)
+ record.rootInstance.__VUE_DEVTOOLS_UID__ = rootId
+
+ // Timeline
+ addBuiltinLayers(record, ctx)
+
+ ctx.appRecords.push(record)
+
+ if (backend.options.setupApp) {
+ backend.options.setupApp(backend.api, record)
+ }
+
+ await backend.api.registerApplication(options.app)
+
+ ctx.bridge.send(BridgeEvents.TO_FRONT_APP_ADD, {
+ appRecord: mapAppRecord(record),
+ })
+
+ // Auto select first app
+ if (ctx.currentAppRecord == null) {
+ await selectApp(record, ctx)
+ }
+
+ if (appRecordPromises.has(options.app)) {
+ for (const r of appRecordPromises.get(options.app)) {
+ await r(record)
+ }
+ }
+ }
+ else if (SharedData.debugInfo) {
+ console.warn('[Vue devtools] No root instance found for app, it might have been unmounted', options.app)
+ }
+}
+
+export async function selectApp(record: AppRecord, ctx: BackendContext) {
+ ctx.currentAppRecord = record
+ ctx.currentInspectedComponentId = record.lastInspectedComponentId
+ ctx.bridge.send(BridgeEvents.TO_FRONT_APP_SELECTED, {
+ id: record.id,
+ lastInspectedComponentId: record.lastInspectedComponentId,
+ })
+}
+
+export function mapAppRecord(record: AppRecord): SimpleAppRecord {
+ return {
+ id: record.id,
+ name: record.name,
+ version: record.options.version,
+ iframe: record.iframe,
+ }
+}
+
+const appIds = new Set()
+
+export function getAppRecordId(app, defaultId?: string): string {
+ if (app.__VUE_DEVTOOLS_APP_RECORD_ID__ != null) {
+ return app.__VUE_DEVTOOLS_APP_RECORD_ID__
+ }
+ let id = defaultId ?? (recordId++).toString()
+
+ if (defaultId && appIds.has(id)) {
+ let count = 1
+ while (appIds.has(`${defaultId}_${count}`)) {
+ count++
+ }
+ id = `${defaultId}_${count}`
+ }
+
+ appIds.add(id)
+
+ app.__VUE_DEVTOOLS_APP_RECORD_ID__ = id
+ return id
+}
+
+export async function getAppRecord(app: any, ctx: BackendContext): Promise {
+ const record = app.__VUE_DEVTOOLS_APP_RECORD__ ?? ctx.appRecords.find(ar => ar.options.app === app)
+ if (record) {
+ return record
+ }
+ if (app._vueDevtools_hidden_) {
+ return null
+ }
+ return new Promise((resolve, reject) => {
+ let resolvers = appRecordPromises.get(app)
+ let timedOut = false
+ if (!resolvers) {
+ resolvers = []
+ appRecordPromises.set(app, resolvers)
+ }
+ let timer: any
+ const fn = (record) => {
+ if (!timedOut) {
+ clearTimeout(timer)
+ resolve(record)
+ }
+ }
+ resolvers.push(fn)
+ timer = setTimeout(() => {
+ timedOut = true
+ const index = resolvers.indexOf(fn)
+ if (index !== -1) {
+ resolvers.splice(index, 1)
+ }
+ if (SharedData.debugInfo) {
+ // eslint-disable-next-line no-console
+ console.log('Timed out waiting for app record', app)
+ }
+ reject(new Error(`Timed out getting app record for app`))
+ }, 60000)
+ })
+}
+
+export function waitForAppsRegistration() {
+ return jobs.queue('waitForAppsRegistrationNoop', async () => { /* NOOP */ })
+}
+
+export async function sendApps(ctx: BackendContext) {
+ const appRecords = []
+
+ for (const appRecord of ctx.appRecords) {
+ appRecords.push(appRecord)
+ }
+
+ ctx.bridge.send(BridgeEvents.TO_FRONT_APP_LIST, {
+ apps: appRecords.map(mapAppRecord),
+ })
+}
+
+function removeAppRecord(appRecord: AppRecord, ctx: BackendContext) {
+ try {
+ appIds.delete(appRecord.id)
+ const index = ctx.appRecords.indexOf(appRecord)
+ if (index !== -1) {
+ ctx.appRecords.splice(index, 1)
+ }
+ removeLayersForApp(appRecord.options.app, ctx)
+ ctx.bridge.send(BridgeEvents.TO_FRONT_APP_REMOVE, { id: appRecord.id })
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+}
+
+export async function removeApp(app: App, ctx: BackendContext) {
+ try {
+ const appRecord = await getAppRecord(app, ctx)
+ if (appRecord) {
+ removeAppRecord(appRecord, ctx)
+ }
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+}
+
+let scanTimeout: any
+
+export function _legacy_getAndRegisterApps(ctx: BackendContext, clear = false) {
+ setTimeout(() => {
+ try {
+ if (clear) {
+ // Remove apps that are legacy
+ ctx.appRecords.forEach((appRecord) => {
+ if (appRecord.meta.Vue) {
+ removeAppRecord(appRecord, ctx)
+ }
+ })
+ }
+
+ const apps = scan()
+
+ clearTimeout(scanTimeout)
+ if (!apps.length) {
+ scanTimeout = setTimeout(() => _legacy_getAndRegisterApps(ctx), 1000)
+ }
+
+ apps.forEach((app) => {
+ const Vue = hook.Vue
+ registerApp({
+ app,
+ types: {},
+ version: Vue?.version,
+ meta: {
+ Vue,
+ },
+ }, ctx)
+ })
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(`Error scanning for legacy apps:`)
+ console.error(e)
+ }
+ }
+ }, 0)
+}
diff --git a/vue-devtools/packages/app-backend-core/src/backend.ts b/vue-devtools/packages/app-backend-core/src/backend.ts
new file mode 100644
index 0000000000000000000000000000000000000000..af07e8244d954aa3a44328c26bcf33092ab8fdcb
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/backend.ts
@@ -0,0 +1,31 @@
+import type { BackendContext, DevtoolsBackend, DevtoolsBackendOptions } from '@vue-devtools/app-backend-api'
+import { createBackend } from '@vue-devtools/app-backend-api'
+
+import { backend as backendVue1 } from '@vue-devtools/app-backend-vue1'
+import { backend as backendVue2 } from '@vue-devtools/app-backend-vue2'
+import { backend as backendVue3 } from '@vue-devtools/app-backend-vue3'
+
+import { handleAddPerformanceTag } from './perf'
+
+export const availableBackends = [
+ backendVue1,
+ backendVue2,
+ backendVue3,
+]
+
+const enabledBackends: Map = new Map()
+
+export function getBackend(backendOptions: DevtoolsBackendOptions, ctx: BackendContext) {
+ let backend: DevtoolsBackend
+ if (!enabledBackends.has(backendOptions)) {
+ // Create backend
+ backend = createBackend(backendOptions, ctx)
+ handleAddPerformanceTag(backend, ctx)
+ enabledBackends.set(backendOptions, backend)
+ ctx.backends.push(backend)
+ }
+ else {
+ backend = enabledBackends.get(backendOptions)
+ }
+ return backend
+}
diff --git a/vue-devtools/packages/app-backend-core/src/component-pick.ts b/vue-devtools/packages/app-backend-core/src/component-pick.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ca23a94facb4b7e4b58c9e9407d14804424c29af
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/component-pick.ts
@@ -0,0 +1,114 @@
+import { BridgeEvents, isBrowser } from '@vue-devtools/shared-utils'
+import type { BackendContext, DevtoolsBackend } from '@vue-devtools/app-backend-api'
+import type { ComponentInstance } from '@vue/devtools-api'
+import { highlight, unHighlight } from './highlighter'
+
+export default class ComponentPicker {
+ ctx: BackendContext
+ selectedInstance: ComponentInstance
+ selectedBackend: DevtoolsBackend
+
+ constructor(ctx: BackendContext) {
+ this.ctx = ctx
+ this.bindMethods()
+ }
+
+ /**
+ * Adds event listeners for mouseover and mouseup
+ */
+ startSelecting() {
+ if (!isBrowser) {
+ return
+ }
+ window.addEventListener('mouseover', this.elementMouseOver, true)
+ window.addEventListener('click', this.elementClicked, true)
+ window.addEventListener('mouseout', this.cancelEvent, true)
+ window.addEventListener('mouseenter', this.cancelEvent, true)
+ window.addEventListener('mouseleave', this.cancelEvent, true)
+ window.addEventListener('mousedown', this.cancelEvent, true)
+ window.addEventListener('mouseup', this.cancelEvent, true)
+ }
+
+ /**
+ * Removes event listeners
+ */
+ stopSelecting() {
+ if (!isBrowser) {
+ return
+ }
+ window.removeEventListener('mouseover', this.elementMouseOver, true)
+ window.removeEventListener('click', this.elementClicked, true)
+ window.removeEventListener('mouseout', this.cancelEvent, true)
+ window.removeEventListener('mouseenter', this.cancelEvent, true)
+ window.removeEventListener('mouseleave', this.cancelEvent, true)
+ window.removeEventListener('mousedown', this.cancelEvent, true)
+ window.removeEventListener('mouseup', this.cancelEvent, true)
+
+ unHighlight()
+ }
+
+ /**
+ * Highlights a component on element mouse over
+ */
+ async elementMouseOver(e: MouseEvent) {
+ this.cancelEvent(e)
+
+ const el = e.target
+ if (el) {
+ await this.selectElementComponent(el)
+ }
+
+ unHighlight()
+ if (this.selectedInstance) {
+ highlight(this.selectedInstance, this.selectedBackend, this.ctx)
+ }
+ }
+
+ async selectElementComponent(el) {
+ for (const backend of this.ctx.backends) {
+ const instance = await backend.api.getElementComponent(el)
+ if (instance) {
+ this.selectedInstance = instance
+ this.selectedBackend = backend
+ return
+ }
+ }
+ this.selectedInstance = null
+ this.selectedBackend = null
+ }
+
+ /**
+ * Selects an instance in the component view
+ */
+ async elementClicked(e: MouseEvent) {
+ this.cancelEvent(e)
+
+ if (this.selectedInstance && this.selectedBackend) {
+ const parentInstances = await this.selectedBackend.api.walkComponentParents(this.selectedInstance)
+ this.ctx.bridge.send(BridgeEvents.TO_FRONT_COMPONENT_PICK, { id: this.selectedInstance.__VUE_DEVTOOLS_UID__, parentIds: parentInstances.map(i => i.__VUE_DEVTOOLS_UID__) })
+ }
+ else {
+ this.ctx.bridge.send(BridgeEvents.TO_FRONT_COMPONENT_PICK_CANCELED, null)
+ }
+
+ this.stopSelecting()
+ }
+
+ /**
+ * Cancel a mouse event
+ */
+ cancelEvent(e: MouseEvent) {
+ e.stopImmediatePropagation()
+ e.preventDefault()
+ }
+
+ /**
+ * Bind class methods to the class scope to avoid rebind for event listeners
+ */
+ bindMethods() {
+ this.startSelecting = this.startSelecting.bind(this)
+ this.stopSelecting = this.stopSelecting.bind(this)
+ this.elementMouseOver = this.elementMouseOver.bind(this)
+ this.elementClicked = this.elementClicked.bind(this)
+ }
+}
diff --git a/vue-devtools/packages/app-backend-core/src/component.ts b/vue-devtools/packages/app-backend-core/src/component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4033b792fb467ae18edbda42ed4ffcadd9ae11aa
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/component.ts
@@ -0,0 +1,169 @@
+import { BridgeEvents, SharedData, createThrottleQueue, parse, stringify } from '@vue-devtools/shared-utils'
+import type { AppRecord, BackendContext } from '@vue-devtools/app-backend-api'
+import { BuiltinBackendFeature } from '@vue-devtools/app-backend-api'
+import type { App, ComponentInstance, EditStatePayload } from '@vue/devtools-api'
+import { getAppRecord } from './app'
+
+const MAX_$VM = 10
+const $vmQueue = []
+
+export async function sendComponentTreeData(appRecord: AppRecord, instanceId: string, filter = '', maxDepth: number = null, recursively = false, ctx: BackendContext) {
+ if (!instanceId || appRecord !== ctx.currentAppRecord) {
+ return
+ }
+
+ // Flush will send all components in the tree
+ // So we skip individiual tree updates
+ if (
+ instanceId !== '_root'
+ && ctx.currentAppRecord.backend.options.features.includes(BuiltinBackendFeature.FLUSH)
+ ) {
+ return
+ }
+
+ const instance = getComponentInstance(appRecord, instanceId, ctx)
+ if (!instance) {
+ ctx.bridge.send(BridgeEvents.TO_FRONT_COMPONENT_TREE, {
+ instanceId,
+ treeData: null,
+ notFound: true,
+ })
+ }
+ else {
+ if (filter) {
+ filter = filter.toLowerCase()
+ }
+ if (maxDepth == null) {
+ maxDepth = instance === ctx.currentAppRecord.rootInstance ? 2 : 1
+ }
+ const data = await appRecord.backend.api.walkComponentTree(instance, maxDepth, filter, recursively)
+ const payload = {
+ instanceId,
+ treeData: stringify(data),
+ }
+ ctx.bridge.send(BridgeEvents.TO_FRONT_COMPONENT_TREE, payload)
+ }
+}
+
+export async function sendSelectedComponentData(appRecord: AppRecord, instanceId: string, ctx: BackendContext) {
+ if (!instanceId || appRecord !== ctx.currentAppRecord) {
+ return
+ }
+ const instance = getComponentInstance(appRecord, instanceId, ctx)
+ if (!instance) {
+ sendEmptyComponentData(instanceId, ctx)
+ }
+ else {
+ // Expose instance on window
+ if (typeof window !== 'undefined') {
+ const win = window as any
+ win.$vm = instance
+
+ // $vm0, $vm1, $vm2, ...
+ if ($vmQueue[0] !== instance) {
+ if ($vmQueue.length >= MAX_$VM) {
+ $vmQueue.pop()
+ }
+ for (let i = $vmQueue.length; i > 0; i--) {
+ win[`$vm${i}`] = $vmQueue[i] = $vmQueue[i - 1]
+ }
+ win.$vm0 = $vmQueue[0] = instance
+ }
+ }
+ if (SharedData.debugInfo) {
+ // eslint-disable-next-line no-console
+ console.log('[DEBUG] inspect', instance)
+ }
+ const parentInstances = await appRecord.backend.api.walkComponentParents(instance)
+ const payload = {
+ instanceId,
+ data: stringify(await appRecord.backend.api.inspectComponent(instance, ctx.currentAppRecord.options.app)),
+ parentIds: parentInstances.map(i => i.__VUE_DEVTOOLS_UID__),
+ }
+ ctx.bridge.send(BridgeEvents.TO_FRONT_COMPONENT_SELECTED_DATA, payload)
+ markSelectedInstance(instanceId, ctx)
+ }
+}
+
+export function markSelectedInstance(instanceId: string, ctx: BackendContext) {
+ ctx.currentInspectedComponentId = instanceId
+ ctx.currentAppRecord.lastInspectedComponentId = instanceId
+}
+
+export function sendEmptyComponentData(instanceId: string, ctx: BackendContext) {
+ ctx.bridge.send(BridgeEvents.TO_FRONT_COMPONENT_SELECTED_DATA, {
+ instanceId,
+ data: null,
+ })
+}
+
+export async function editComponentState(instanceId: string, dotPath: string, type: string, state: EditStatePayload, ctx: BackendContext) {
+ if (!instanceId) {
+ return
+ }
+ const instance = getComponentInstance(ctx.currentAppRecord, instanceId, ctx)
+ if (instance) {
+ if ('value' in state && state.value != null) {
+ state.value = parse(state.value, true)
+ }
+ await ctx.currentAppRecord.backend.api.editComponentState(instance, dotPath, type, state, ctx.currentAppRecord.options.app)
+ await sendSelectedComponentData(ctx.currentAppRecord, instanceId, ctx)
+ }
+}
+
+export async function getComponentId(app: App, uid: number, instance: ComponentInstance, ctx: BackendContext) {
+ try {
+ if (instance.__VUE_DEVTOOLS_UID__) {
+ return instance.__VUE_DEVTOOLS_UID__
+ }
+ const appRecord = await getAppRecord(app, ctx)
+ if (!appRecord) {
+ return null
+ }
+ const isRoot = appRecord.rootInstance === instance
+ return `${appRecord.id}:${isRoot ? 'root' : uid}`
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ return null
+ }
+}
+
+export function getComponentInstance(appRecord: AppRecord, instanceId: string, _ctx: BackendContext) {
+ if (instanceId === '_root') {
+ instanceId = `${appRecord.id}:root`
+ }
+ const instance = appRecord.instanceMap.get(instanceId)
+ if (!instance) {
+ appRecord.missingInstanceQueue.add(instanceId)
+ if (SharedData.debugInfo) {
+ console.warn(`Instance uid=${instanceId} not found`)
+ }
+ }
+ return instance
+}
+
+export async function refreshComponentTreeSearch(ctx: BackendContext) {
+ if (!ctx.currentAppRecord.componentFilter) {
+ return
+ }
+ await sendComponentTreeData(ctx.currentAppRecord, '_root', ctx.currentAppRecord.componentFilter, null, false, ctx)
+}
+
+const updateTrackingQueue = createThrottleQueue(500)
+
+export function sendComponentUpdateTracking(instanceId: string, time: number, ctx: BackendContext) {
+ if (!instanceId) {
+ return
+ }
+
+ updateTrackingQueue.add(instanceId, () => {
+ const payload = {
+ instanceId,
+ time,
+ }
+ ctx.bridge.send(BridgeEvents.TO_FRONT_COMPONENT_UPDATED, payload)
+ })
+}
diff --git a/vue-devtools/packages/app-backend-core/src/flash.ts b/vue-devtools/packages/app-backend-core/src/flash.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8c9bdf38ab0ffbfa4b617faf758b6bef27b7c7c8
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/flash.ts
@@ -0,0 +1,35 @@
+import type { DevtoolsBackend } from '@vue-devtools/app-backend-api'
+import type { ComponentInstance } from '@vue/devtools-api'
+
+export async function flashComponent(instance: ComponentInstance, backend: DevtoolsBackend) {
+ const bounds = await backend.api.getComponentBounds(instance)
+ if (bounds) {
+ let overlay: HTMLDivElement = instance.__VUE_DEVTOOLS_FLASH
+ if (!overlay) {
+ overlay = document.createElement('div')
+ instance.__VUE_DEVTOOLS_FLASH = overlay
+ overlay.style.border = '2px rgba(65, 184, 131, 0.7) solid'
+ overlay.style.position = 'fixed'
+ overlay.style.zIndex = '99999999999998'
+ overlay.style.pointerEvents = 'none'
+ overlay.style.borderRadius = '3px'
+ overlay.style.boxSizing = 'border-box'
+ document.body.appendChild(overlay)
+ }
+ overlay.style.opacity = '1'
+ overlay.style.transition = null
+ overlay.style.width = `${Math.round(bounds.width)}px`
+ overlay.style.height = `${Math.round(bounds.height)}px`
+ overlay.style.left = `${Math.round(bounds.left)}px`
+ overlay.style.top = `${Math.round(bounds.top)}px`
+ requestAnimationFrame(() => {
+ overlay.style.transition = 'opacity 1s'
+ overlay.style.opacity = '0'
+ })
+ clearTimeout((overlay as any)._timer)
+ ;(overlay as any)._timer = setTimeout(() => {
+ document.body.removeChild(overlay)
+ instance.__VUE_DEVTOOLS_FLASH = null
+ }, 1000)
+ }
+}
diff --git a/vue-devtools/packages/app-backend-core/src/global-hook.ts b/vue-devtools/packages/app-backend-core/src/global-hook.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bbdcd3eaa7c3e2be4fc26b0d3cbd46064f454744
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/global-hook.ts
@@ -0,0 +1,5 @@
+import type { DevtoolsHook } from '@vue-devtools/app-backend-api'
+import { target } from '@vue-devtools/shared-utils'
+
+// hook should have been injected before this executes.
+export const hook: DevtoolsHook = target.__VUE_DEVTOOLS_GLOBAL_HOOK__
diff --git a/vue-devtools/packages/app-backend-core/src/highlighter.ts b/vue-devtools/packages/app-backend-core/src/highlighter.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6a2cb9247ac19eb7dc59c67e188e52b367be078e
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/highlighter.ts
@@ -0,0 +1,168 @@
+import { isBrowser } from '@vue-devtools/shared-utils'
+import type { BackendContext, DevtoolsBackend } from '@vue-devtools/app-backend-api'
+import type { ComponentBounds, ComponentInstance } from '@vue/devtools-api'
+import { JobQueue } from './util/queue'
+
+let overlay: HTMLDivElement
+let overlayContent: HTMLDivElement
+let currentInstance
+
+function createOverlay() {
+ if (overlay || !isBrowser) {
+ return
+ }
+ overlay = document.createElement('div')
+ overlay.style.backgroundColor = 'rgba(65, 184, 131, 0.35)'
+ overlay.style.position = 'fixed'
+ overlay.style.zIndex = '99999999999998'
+ overlay.style.pointerEvents = 'none'
+ overlay.style.borderRadius = '3px'
+ overlayContent = document.createElement('div')
+ overlayContent.style.position = 'fixed'
+ overlayContent.style.zIndex = '99999999999999'
+ overlayContent.style.pointerEvents = 'none'
+ overlayContent.style.backgroundColor = 'white'
+ overlayContent.style.fontFamily = 'monospace'
+ overlayContent.style.fontSize = '11px'
+ overlayContent.style.padding = '4px 8px'
+ overlayContent.style.borderRadius = '3px'
+ overlayContent.style.color = '#333'
+ overlayContent.style.textAlign = 'center'
+ overlayContent.style.border = 'rgba(65, 184, 131, 0.5) 1px solid'
+ overlayContent.style.backgroundClip = 'padding-box'
+}
+
+// Use a job queue to preserve highlight/unhighlight calls order
+// This prevents "sticky" highlights that are not removed because highlight is async
+const jobQueue = new JobQueue()
+
+export async function highlight(instance: ComponentInstance, backend: DevtoolsBackend, ctx: BackendContext) {
+ await jobQueue.queue('highlight', async () => {
+ if (!instance) {
+ return
+ }
+
+ const bounds = await backend.api.getComponentBounds(instance)
+ if (bounds) {
+ createOverlay()
+
+ // Name
+ const name = (await backend.api.getComponentName(instance)) || 'Anonymous'
+ const pre = document.createElement('span')
+ pre.style.opacity = '0.6'
+ pre.textContent = '<'
+ const text = document.createElement('span')
+ text.style.fontWeight = 'bold'
+ text.style.color = '#09ab56'
+ text.textContent = name
+ const post = document.createElement('span')
+ post.style.opacity = '0.6'
+ post.textContent = '>'
+
+ // Size
+ const size = document.createElement('span')
+ size.style.opacity = '0.5'
+ size.style.marginLeft = '6px'
+ size.appendChild(document.createTextNode((Math.round(bounds.width * 100) / 100).toString()))
+ const multiply = document.createElement('span')
+ multiply.style.marginLeft = multiply.style.marginRight = '2px'
+ multiply.textContent = '×'
+ size.appendChild(multiply)
+ size.appendChild(document.createTextNode((Math.round(bounds.height * 100) / 100).toString()))
+
+ currentInstance = instance
+
+ await showOverlay(bounds, [pre, text, post, size])
+ }
+
+ startUpdateTimer(backend, ctx)
+ })
+}
+
+export async function unHighlight() {
+ await jobQueue.queue('unHighlight', async () => {
+ overlay?.parentNode?.removeChild(overlay)
+ overlayContent?.parentNode?.removeChild(overlayContent)
+ currentInstance = null
+
+ stopUpdateTimer()
+ })
+}
+
+function showOverlay(bounds: ComponentBounds, children: Node[] = null) {
+ if (!isBrowser || !children.length) {
+ return
+ }
+
+ positionOverlay(bounds)
+ document.body.appendChild(overlay)
+
+ overlayContent.innerHTML = ''
+ children.forEach(child => overlayContent.appendChild(child))
+ document.body.appendChild(overlayContent)
+
+ positionOverlayContent(bounds)
+}
+
+function positionOverlay({ width = 0, height = 0, top = 0, left = 0 }) {
+ overlay.style.width = `${Math.round(width)}px`
+ overlay.style.height = `${Math.round(height)}px`
+ overlay.style.left = `${Math.round(left)}px`
+ overlay.style.top = `${Math.round(top)}px`
+}
+
+function positionOverlayContent({ height = 0, top = 0, left = 0 }) {
+ // Content position (prevents overflow)
+ const contentWidth = overlayContent.offsetWidth
+ const contentHeight = overlayContent.offsetHeight
+ let contentLeft = left
+ if (contentLeft < 0) {
+ contentLeft = 0
+ }
+ else if (contentLeft + contentWidth > window.innerWidth) {
+ contentLeft = window.innerWidth - contentWidth
+ }
+ let contentTop = top - contentHeight - 2
+ if (contentTop < 0) {
+ contentTop = top + height + 2
+ }
+ if (contentTop < 0) {
+ contentTop = 0
+ }
+ else if (contentTop + contentHeight > window.innerHeight) {
+ contentTop = window.innerHeight - contentHeight
+ }
+ overlayContent.style.left = `${~~contentLeft}px`
+ overlayContent.style.top = `${~~contentTop}px`
+}
+
+async function updateOverlay(backend: DevtoolsBackend, _ctx: BackendContext) {
+ if (currentInstance) {
+ const bounds = await backend.api.getComponentBounds(currentInstance)
+ if (bounds) {
+ const sizeEl = overlayContent.children.item(3)
+ const widthEl = sizeEl.childNodes[0] as unknown as Text
+ widthEl.textContent = (Math.round(bounds.width * 100) / 100).toString()
+ const heightEl = sizeEl.childNodes[2] as unknown as Text
+ heightEl.textContent = (Math.round(bounds.height * 100) / 100).toString()
+
+ positionOverlay(bounds)
+ positionOverlayContent(bounds)
+ }
+ }
+}
+
+let updateTimer
+
+function startUpdateTimer(backend: DevtoolsBackend, ctx: BackendContext) {
+ stopUpdateTimer()
+ updateTimer = setInterval(() => {
+ jobQueue.queue('updateOverlay', async () => {
+ await updateOverlay(backend, ctx)
+ })
+ }, 1000 / 30) // 30fps
+}
+
+function stopUpdateTimer() {
+ clearInterval(updateTimer)
+}
diff --git a/vue-devtools/packages/app-backend-core/src/hook.ts b/vue-devtools/packages/app-backend-core/src/hook.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c13558a6f5b9e0d05fb1a8560282cb9024f7ab9a
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/hook.ts
@@ -0,0 +1,746 @@
+// this script is injected into every page.
+
+/**
+ * Install the hook on window, which is an event emitter.
+ * Note because Chrome content scripts cannot directly modify the window object,
+ * we are evaling this function by inserting a script tag. That's why we have
+ * to inline the whole event emitter implementation here.
+ *
+ * @param {Window|global} target
+ */
+export function installHook(target, isIframe = false) {
+ const devtoolsVersion = '6.0'
+ let listeners = {}
+
+ function injectIframeHook(iframe) {
+ if ((iframe as any).__vdevtools__injected) {
+ return
+ }
+ try {
+ (iframe as any).__vdevtools__injected = true
+ const inject = () => {
+ try {
+ (iframe.contentWindow as any).__VUE_DEVTOOLS_IFRAME__ = iframe
+ const script = iframe.contentDocument.createElement('script')
+ script.textContent = `;(${installHook.toString()})(window, true)`
+ iframe.contentDocument.documentElement.appendChild(script)
+ script.parentNode.removeChild(script)
+ }
+ catch (e) {
+ // Ignore
+ }
+ }
+ inject()
+ iframe.addEventListener('load', () => inject())
+ }
+ catch (e) {
+ // Ignore
+ }
+ }
+
+ let iframeChecks = 0
+ function injectToIframes() {
+ if (typeof window === 'undefined') {
+ return
+ }
+
+ const iframes = document.querySelectorAll('iframe:not([data-vue-devtools-ignore])')
+ for (const iframe of iframes) {
+ injectIframeHook(iframe)
+ }
+ }
+ injectToIframes()
+ const iframeTimer = setInterval(() => {
+ injectToIframes()
+ iframeChecks++
+ if (iframeChecks >= 5) {
+ clearInterval(iframeTimer)
+ }
+ }, 1000)
+
+ if (Object.prototype.hasOwnProperty.call(target, '__VUE_DEVTOOLS_GLOBAL_HOOK__')) {
+ if (target.__VUE_DEVTOOLS_GLOBAL_HOOK__.devtoolsVersion !== devtoolsVersion) {
+ console.error(`Another version of Vue Devtools seems to be installed. Please enable only one version at a time.`)
+ }
+ return
+ }
+
+ let hook
+
+ if (isIframe) {
+ const sendToParent = (cb) => {
+ try {
+ const hook = (window.parent as any).__VUE_DEVTOOLS_GLOBAL_HOOK__
+ if (hook) {
+ return cb(hook)
+ }
+ else {
+ console.warn('[Vue Devtools] No hook in parent window')
+ }
+ }
+ catch (e) {
+ console.warn('[Vue Devtools] Failed to send message to parent window', e)
+ }
+ }
+
+ hook = {
+ devtoolsVersion,
+ // eslint-disable-next-line accessor-pairs
+ set Vue(value) {
+ sendToParent((hook) => {
+ hook.Vue = value
+ })
+ },
+
+ // eslint-disable-next-line accessor-pairs
+ set enabled(value) {
+ sendToParent((hook) => {
+ hook.enabled = value
+ })
+ },
+
+ on(event, fn) {
+ sendToParent(hook => hook.on(event, fn))
+ },
+
+ once(event, fn) {
+ sendToParent(hook => hook.once(event, fn))
+ },
+
+ off(event, fn) {
+ sendToParent(hook => hook.off(event, fn))
+ },
+
+ emit(event, ...args) {
+ sendToParent(hook => hook.emit(event, ...args))
+ },
+
+ cleanupBuffer(matchArg) {
+ return sendToParent(hook => hook.cleanupBuffer(matchArg)) ?? false
+ },
+ }
+ }
+ else {
+ hook = {
+ devtoolsVersion,
+ Vue: null,
+ enabled: undefined,
+ _buffer: [],
+ _bufferMap: new Map(),
+ _bufferToRemove: new Map(),
+ store: null,
+ initialState: null,
+ storeModules: null,
+ flushStoreModules: null,
+ apps: [],
+
+ _replayBuffer(event) {
+ const buffer = this._buffer
+ this._buffer = []
+ this._bufferMap.clear()
+ this._bufferToRemove.clear()
+
+ for (let i = 0, l = buffer.length; i < l; i++) {
+ const allArgs = buffer[i].slice(1)
+ allArgs[0] === event
+ // eslint-disable-next-line prefer-spread
+ ? this.emit.apply(this, allArgs)
+ : this._buffer.push(buffer[i])
+ }
+ },
+
+ on(event, fn) {
+ const $event = `$${event}`
+ if (listeners[$event]) {
+ listeners[$event].push(fn)
+ }
+ else {
+ listeners[$event] = [fn]
+ this._replayBuffer(event)
+ }
+ },
+
+ once(event, fn) {
+ const on = (...args) => {
+ this.off(event, on)
+ return fn.apply(this, args)
+ }
+ this.on(event, on)
+ },
+
+ off(event, fn) {
+ event = `$${event}`
+ if (!arguments.length) {
+ listeners = {}
+ }
+ else {
+ const cbs = listeners[event]
+ if (cbs) {
+ if (!fn) {
+ listeners[event] = null
+ }
+ else {
+ for (let i = 0, l = cbs.length; i < l; i++) {
+ const cb = cbs[i]
+ if (cb === fn || cb.fn === fn) {
+ cbs.splice(i, 1)
+ break
+ }
+ }
+ }
+ }
+ }
+ },
+
+ emit(event, ...args) {
+ const $event = `$${event}`
+ let cbs = listeners[$event]
+ if (cbs) {
+ cbs = cbs.slice()
+ for (let i = 0, l = cbs.length; i < l; i++) {
+ try {
+ const result = cbs[i].apply(this, args)
+ if (typeof result?.catch === 'function') {
+ result.catch((e) => {
+ console.error(`[Hook] Error in async event handler for ${event} with args:`, args)
+ console.error(e)
+ })
+ }
+ }
+ catch (e) {
+ console.error(`[Hook] Error in event handler for ${event} with args:`, args)
+ console.error(e)
+ }
+ }
+ }
+ else {
+ const buffered = [Date.now(), event, ...args]
+ this._buffer.push(buffered)
+
+ for (let i = 2; i < args.length; i++) {
+ if (typeof args[i] === 'object' && args[i]) {
+ // Save by component instance (3rd, 4th or 5th arg)
+ this._bufferMap.set(args[i], buffered)
+ break
+ }
+ }
+ }
+ },
+
+ /**
+ * Remove buffered events with any argument that is equal to the given value.
+ * @param matchArg Given value to match.
+ */
+ cleanupBuffer(matchArg) {
+ const inBuffer = this._bufferMap.has(matchArg)
+ if (inBuffer) {
+ // Mark event for removal
+ this._bufferToRemove.set(this._bufferMap.get(matchArg), true)
+ }
+ return inBuffer
+ },
+
+ _cleanupBuffer() {
+ const now = Date.now()
+ // Clear buffer events that are older than 10 seconds or marked for removal
+ this._buffer = this._buffer.filter(args => !this._bufferToRemove.has(args) && now - args[0] < 10_000)
+ this._bufferToRemove.clear()
+ this._bufferMap.clear()
+ },
+ }
+
+ setInterval(() => {
+ hook._cleanupBuffer()
+ }, 10_000)
+
+ hook.once('init', (Vue) => {
+ hook.Vue = Vue
+
+ if (Vue) {
+ Vue.prototype.$inspect = function () {
+ const fn = target.__VUE_DEVTOOLS_INSPECT__
+ fn && fn(this)
+ }
+ }
+ })
+
+ hook.on('app:init', (app, version, types) => {
+ const appRecord = {
+ app,
+ version,
+ types,
+ }
+ hook.apps.push(appRecord)
+ hook.emit('app:add', appRecord)
+ })
+
+ hook.once('vuex:init', (store) => {
+ hook.store = store
+ hook.initialState = clone(store.state)
+ const origReplaceState = store.replaceState.bind(store)
+ store.replaceState = (state) => {
+ hook.initialState = clone(state)
+ origReplaceState(state)
+ }
+ // Dynamic modules
+ let origRegister, origUnregister
+ if (store.registerModule) {
+ hook.storeModules = []
+ origRegister = store.registerModule.bind(store)
+ store.registerModule = (path, module, options) => {
+ if (typeof path === 'string') {
+ path = [path]
+ }
+ hook.storeModules.push({ path, module, options })
+ origRegister(path, module, options)
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log('early register module', path, module, options)
+ }
+ }
+ origUnregister = store.unregisterModule.bind(store)
+ store.unregisterModule = (path) => {
+ if (typeof path === 'string') {
+ path = [path]
+ }
+ const key = path.join('/')
+ const index = hook.storeModules.findIndex(m => m.path.join('/') === key)
+ if (index !== -1) {
+ hook.storeModules.splice(index, 1)
+ }
+ origUnregister(path)
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log('early unregister module', path)
+ }
+ }
+ }
+ hook.flushStoreModules = () => {
+ store.replaceState = origReplaceState
+ if (store.registerModule) {
+ store.registerModule = origRegister
+ store.unregisterModule = origUnregister
+ }
+ return hook.storeModules || []
+ }
+ })
+ }
+
+ Object.defineProperty(target, '__VUE_DEVTOOLS_GLOBAL_HOOK__', {
+ get() {
+ return hook
+ },
+ })
+
+ // Handle apps initialized before hook injection
+ if (target.__VUE_DEVTOOLS_HOOK_REPLAY__) {
+ try {
+ target.__VUE_DEVTOOLS_HOOK_REPLAY__.forEach(cb => cb(hook))
+ target.__VUE_DEVTOOLS_HOOK_REPLAY__ = []
+ }
+ catch (e) {
+ console.error('[vue-devtools] Error during hook replay', e)
+ }
+ }
+
+ // Clone deep utility for cloning initial state of the store
+ // Forked from https://github.com/planttheidea/fast-copy
+ // Last update: 2019-10-30
+ // ⚠️ Don't forget to update `./hook.js`
+
+ // utils
+ const { toString: toStringFunction } = Function.prototype
+ const {
+ create,
+ defineProperty,
+ getOwnPropertyDescriptor,
+ getOwnPropertyNames,
+ getOwnPropertySymbols,
+ getPrototypeOf,
+ } = Object
+ const { hasOwnProperty, propertyIsEnumerable } = Object.prototype
+
+ /**
+ * @enum
+ *
+ * @const {object} SUPPORTS
+ *
+ * @property {boolean} SYMBOL_PROPERTIES are symbol properties supported
+ * @property {boolean} WEAKSET is WeakSet supported
+ */
+ const SUPPORTS = {
+ SYMBOL_PROPERTIES: typeof getOwnPropertySymbols === 'function',
+ WEAKSET: typeof WeakSet === 'function',
+ }
+
+ /**
+ * @function createCache
+ *
+ * @description
+ * get a new cache object to prevent circular references
+ *
+ * @returns the new cache object
+ */
+ const createCache = () => {
+ if (SUPPORTS.WEAKSET) {
+ return new WeakSet()
+ }
+
+ const object = create({
+ add: value => object._values.push(value),
+ has: value => !!~object._values.indexOf(value),
+ })
+
+ object._values = []
+
+ return object
+ }
+
+ /**
+ * @function getCleanClone
+ *
+ * @description
+ * get an empty version of the object with the same prototype it has
+ *
+ * @param object the object to build a clean clone from
+ * @param realm the realm the object resides in
+ * @returns the empty cloned object
+ */
+ const getCleanClone = (object, realm) => {
+ if (!object.constructor) {
+ return create(null)
+ }
+
+ // eslint-disable-next-line no-proto, no-restricted-properties
+ const prototype = object.__proto__ || getPrototypeOf(object)
+
+ if (object.constructor === realm.Object) {
+ return prototype === realm.Object.prototype ? {} : create(prototype)
+ }
+
+ if (~toStringFunction.call(object.constructor).indexOf('[native code]')) {
+ try {
+ return new object.constructor()
+ }
+ catch (e) {
+ // Error
+ }
+ }
+
+ return create(prototype)
+ }
+
+ /**
+ * @function getObjectCloneLoose
+ *
+ * @description
+ * get a copy of the object based on loose rules, meaning all enumerable keys
+ * and symbols are copied, but property descriptors are not considered
+ *
+ * @param object the object to clone
+ * @param realm the realm the object resides in
+ * @param handleCopy the function that handles copying the object
+ * @returns the copied object
+ */
+ const getObjectCloneLoose = (
+ object,
+ realm,
+ handleCopy,
+ cache,
+ ) => {
+ const clone = getCleanClone(object, realm)
+
+ for (const key in object) {
+ if (hasOwnProperty.call(object, key)) {
+ clone[key] = handleCopy(object[key], cache)
+ }
+ }
+
+ if (SUPPORTS.SYMBOL_PROPERTIES) {
+ const symbols = getOwnPropertySymbols(object)
+
+ if (symbols.length) {
+ for (let index = 0, symbol; index < symbols.length; index++) {
+ symbol = symbols[index]
+
+ if (propertyIsEnumerable.call(object, symbol)) {
+ clone[symbol] = handleCopy(object[symbol], cache)
+ }
+ }
+ }
+ }
+
+ return clone
+ }
+
+ /**
+ * @function getObjectCloneStrict
+ *
+ * @description
+ * get a copy of the object based on strict rules, meaning all keys and symbols
+ * are copied based on the original property descriptors
+ *
+ * @param object the object to clone
+ * @param realm the realm the object resides in
+ * @param handleCopy the function that handles copying the object
+ * @returns the copied object
+ */
+ const getObjectCloneStrict = (
+ object,
+ realm,
+ handleCopy,
+ cache,
+ ) => {
+ const clone = getCleanClone(object, realm)
+
+ const properties = SUPPORTS.SYMBOL_PROPERTIES
+ ? [].concat(getOwnPropertyNames(object), getOwnPropertySymbols(object))
+ : getOwnPropertyNames(object)
+
+ if (properties.length) {
+ for (
+ let index = 0, property, descriptor;
+ index < properties.length;
+ index++
+ ) {
+ property = properties[index]
+
+ if (property !== 'callee' && property !== 'caller') {
+ descriptor = getOwnPropertyDescriptor(object, property)
+
+ descriptor.value = handleCopy(object[property], cache)
+
+ defineProperty(clone, property, descriptor)
+ }
+ }
+ }
+
+ return clone
+ }
+
+ /**
+ * @function getRegExpFlags
+ *
+ * @description
+ * get the flags to apply to the copied regexp
+ *
+ * @param regExp the regexp to get the flags of
+ * @returns the flags for the regexp
+ */
+ const getRegExpFlags = (regExp) => {
+ let flags = ''
+
+ if (regExp.global) {
+ flags += 'g'
+ }
+
+ if (regExp.ignoreCase) {
+ flags += 'i'
+ }
+
+ if (regExp.multiline) {
+ flags += 'm'
+ }
+
+ if (regExp.unicode) {
+ flags += 'u'
+ }
+
+ if (regExp.sticky) {
+ flags += 'y'
+ }
+
+ return flags
+ }
+
+ const { isArray } = Array
+
+ const GLOBAL_THIS = (() => {
+ // eslint-disable-next-line no-restricted-globals
+ if (typeof self !== 'undefined') {
+ // eslint-disable-next-line no-restricted-globals
+ return self
+ }
+
+ if (typeof window !== 'undefined') {
+ return window
+ }
+
+ if (typeof globalThis !== 'undefined') {
+ return globalThis
+ }
+
+ if (console && console.error) {
+ console.error('Unable to locate global object, returning "this".')
+ }
+ })()
+
+ /**
+ * @function clone
+ *
+ * @description
+ * copy an object deeply as much as possible
+ *
+ * If `strict` is applied, then all properties (including non-enumerable ones)
+ * are copied with their original property descriptors on both objects and arrays.
+ *
+ * The object is compared to the global constructors in the `realm` provided,
+ * and the native constructor is always used to ensure that extensions of native
+ * objects (allows in ES2015+) are maintained.
+ *
+ * @param object the object to copy
+ * @param [options] the options for copying with
+ * @param [options.isStrict] should the copy be strict
+ * @param [options.realm] the realm (this) object the object is copied from
+ * @returns the copied object
+ */
+ function clone(object, options = null) {
+ // manually coalesced instead of default parameters for performance
+ const isStrict = !!(options && options.isStrict)
+ const realm = (options && options.realm) || GLOBAL_THIS
+
+ const getObjectClone = isStrict
+ ? getObjectCloneStrict
+ : getObjectCloneLoose
+
+ /**
+ * @function handleCopy
+ *
+ * @description
+ * copy the object recursively based on its type
+ *
+ * @param object the object to copy
+ * @returns the copied object
+ */
+ const handleCopy = (
+ object,
+ cache,
+ ) => {
+ if (!object || typeof object !== 'object' || cache.has(object)) {
+ return object
+ }
+
+ // DOM objects
+ if (typeof HTMLElement !== 'undefined' && object instanceof HTMLElement) {
+ return object.cloneNode(false)
+ }
+
+ const Constructor = object.constructor
+
+ // plain objects
+ if (Constructor === realm.Object) {
+ cache.add(object)
+
+ return getObjectClone(object, realm, handleCopy, cache)
+ }
+
+ let clone
+
+ // arrays
+ if (isArray(object)) {
+ cache.add(object)
+
+ // if strict, include non-standard properties
+ if (isStrict) {
+ return getObjectCloneStrict(object, realm, handleCopy, cache)
+ }
+
+ clone = new Constructor()
+
+ for (let index = 0; index < object.length; index++) {
+ clone[index] = handleCopy(object[index], cache)
+ }
+
+ return clone
+ }
+
+ // dates
+ if (object instanceof realm.Date) {
+ return new Constructor(object.getTime())
+ }
+
+ // regexps
+ if (object instanceof realm.RegExp) {
+ clone = new Constructor(
+ object.source,
+ object.flags || getRegExpFlags(object),
+ )
+
+ clone.lastIndex = object.lastIndex
+
+ return clone
+ }
+
+ // maps
+ if (realm.Map && object instanceof realm.Map) {
+ cache.add(object)
+
+ clone = new Constructor()
+
+ object.forEach((value, key) => {
+ clone.set(key, handleCopy(value, cache))
+ })
+
+ return clone
+ }
+
+ // sets
+ if (realm.Set && object instanceof realm.Set) {
+ cache.add(object)
+
+ clone = new Constructor()
+
+ object.forEach((value) => {
+ clone.add(handleCopy(value, cache))
+ })
+
+ return clone
+ }
+
+ // buffers (node-only)
+ if (realm.Buffer && realm.Buffer.isBuffer(object)) {
+ clone = realm.Buffer.allocUnsafe
+ ? realm.Buffer.allocUnsafe(object.length)
+ : new Constructor(object.length)
+
+ object.copy(clone)
+
+ return clone
+ }
+
+ // arraybuffers / dataviews
+ if (realm.ArrayBuffer) {
+ // dataviews
+ if (realm.ArrayBuffer.isView(object)) {
+ return new Constructor(object.buffer.slice(0))
+ }
+
+ // arraybuffers
+ if (object instanceof realm.ArrayBuffer) {
+ return object.slice(0)
+ }
+ }
+
+ // if the object cannot / should not be cloned, don't
+ if (
+ // promise-like
+ (hasOwnProperty.call(object, 'then') && typeof object.then === 'function')
+ // errors
+ || object instanceof Error
+ // weakmaps
+ || (realm.WeakMap && object instanceof realm.WeakMap)
+ // weaksets
+ || (realm.WeakSet && object instanceof realm.WeakSet)
+ ) {
+ return object
+ }
+
+ cache.add(object)
+
+ // assume anything left is a custom constructor
+ return getObjectClone(object, realm, handleCopy, cache)
+ }
+
+ return handleCopy(object, createCache())
+ }
+}
diff --git a/vue-devtools/packages/app-backend-core/src/index.ts b/vue-devtools/packages/app-backend-core/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d10c082dc1d5c5f159bd3cb120ac07a80fbdf258
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/index.ts
@@ -0,0 +1,760 @@
+import type {
+ AppRecord,
+ BackendContext,
+ Plugin,
+} from '@vue-devtools/app-backend-api'
+import {
+ BuiltinBackendFeature,
+ createBackendContext,
+} from '@vue-devtools/app-backend-api'
+import type {
+ Bridge,
+} from '@vue-devtools/shared-utils'
+import {
+ BridgeEvents,
+ BridgeSubscriptions,
+ BuiltinTabs,
+ HookEvents,
+ SharedData,
+ createThrottleQueue,
+ getPluginSettings,
+ initSharedData,
+ isBrowser,
+ parse,
+ raf,
+ revive,
+ target,
+} from '@vue-devtools/shared-utils'
+import debounce from 'lodash/debounce'
+import type { CustomInspectorOptions, PluginDescriptor, SetupFunction, TimelineEventOptions, TimelineLayerOptions } from '@vue/devtools-api'
+import { Hooks, now } from '@vue/devtools-api'
+import { hook } from './global-hook'
+import { isSubscribed, subscribe, unsubscribe } from './util/subscriptions'
+import { highlight, unHighlight } from './highlighter'
+import { addTimelineEvent, clearTimeline, sendTimelineEventData, sendTimelineLayerEvents, sendTimelineLayers, setupTimeline } from './timeline'
+import ComponentPicker from './component-pick'
+import {
+ editComponentState,
+ getComponentId,
+ getComponentInstance,
+ refreshComponentTreeSearch,
+ sendComponentTreeData,
+ sendComponentUpdateTracking,
+ sendEmptyComponentData,
+ sendSelectedComponentData,
+} from './component'
+import { addPlugin, addPreviouslyRegisteredPlugins, addQueuedPlugins, sendPluginList } from './plugin'
+import { _legacy_getAndRegisterApps, getAppRecord, registerApp, removeApp, selectApp, sendApps, waitForAppsRegistration } from './app'
+import { editInspectorState, getInspector, getInspectorWithAppId, selectInspectorNode, sendCustomInspectors, sendInspectorState, sendInspectorTree } from './inspector'
+import { showScreenshot } from './timeline-screenshot'
+import { performanceMarkEnd, performanceMarkStart } from './perf'
+import { initOnPageConfig } from './page-config'
+import { addTimelineMarker, sendTimelineMarkers } from './timeline-marker'
+import { flashComponent } from './flash.js'
+
+let ctx: BackendContext = target.__vdevtools_ctx ?? null
+let connected = target.__vdevtools_connected ?? false
+
+let pageTitleObserver: MutationObserver
+
+export async function initBackend(bridge: Bridge) {
+ await initSharedData({
+ bridge,
+ persist: false,
+ })
+
+ SharedData.isBrowser = isBrowser
+
+ initOnPageConfig()
+
+ if (!connected) {
+ // First connect
+ ctx = target.__vdevtools_ctx = createBackendContext({
+ bridge,
+ hook,
+ })
+
+ SharedData.legacyApps = false
+ if (hook.Vue) {
+ connect()
+ _legacy_getAndRegisterApps(ctx, true)
+ SharedData.legacyApps = true
+ }
+ hook.on(HookEvents.INIT, () => {
+ _legacy_getAndRegisterApps(ctx, true)
+ SharedData.legacyApps = true
+ })
+
+ hook.on(HookEvents.APP_ADD, async (app) => {
+ await registerApp(app, ctx)
+ connect()
+ })
+
+ // Add apps that already sent init
+ if (hook.apps.length) {
+ hook.apps.forEach((app) => {
+ registerApp(app, ctx)
+ connect()
+ })
+ }
+ }
+ else {
+ // Reconnect
+ ctx.bridge = bridge
+ connectBridge()
+ ctx.bridge.send(BridgeEvents.TO_FRONT_RECONNECTED)
+ }
+}
+
+async function connect() {
+ if (connected) {
+ return
+ }
+ connected = target.__vdevtools_connected = true
+
+ await waitForAppsRegistration()
+
+ connectBridge()
+
+ ctx.currentTab = BuiltinTabs.COMPONENTS
+
+ // Apps
+
+ hook.on(HookEvents.APP_UNMOUNT, async (app) => {
+ await removeApp(app, ctx)
+ })
+
+ // Components
+
+ const throttleQueue = createThrottleQueue(500)
+
+ hook.on(HookEvents.COMPONENT_UPDATED, async (app, uid, parentUid, component) => {
+ try {
+ if (!app || (typeof uid !== 'number' && !uid) || !component) {
+ return
+ }
+ const now = Date.now()
+
+ let id: string
+ let appRecord: AppRecord
+ if (app && uid != null) {
+ id = await getComponentId(app, uid, component, ctx)
+ appRecord = await getAppRecord(app, ctx)
+ }
+ else {
+ id = ctx.currentInspectedComponentId
+ appRecord = ctx.currentAppRecord
+ }
+
+ throttleQueue.add(`update:${id}`, async () => {
+ try {
+ if (SharedData.trackUpdates) {
+ sendComponentUpdateTracking(id, now, ctx)
+ }
+
+ if (SharedData.flashUpdates) {
+ await flashComponent(component, appRecord.backend)
+ }
+
+ // Update component inspector
+ if (ctx.currentInspectedComponentId === id) {
+ await sendSelectedComponentData(appRecord, ctx.currentInspectedComponentId, ctx)
+ }
+
+ // Update tree (tags)
+ if (isSubscribed(BridgeSubscriptions.COMPONENT_TREE, id)) {
+ await sendComponentTreeData(appRecord, id, appRecord.componentFilter, 0, false, ctx)
+ }
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+ })
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+ })
+
+ hook.on(HookEvents.COMPONENT_ADDED, async (app, uid, parentUid, component) => {
+ try {
+ if (!app || (typeof uid !== 'number' && !uid) || !component) {
+ return
+ }
+ const now = Date.now()
+ const id = await getComponentId(app, uid, component, ctx)
+
+ throttleQueue.add(`add:${id}`, async () => {
+ try {
+ const appRecord = await getAppRecord(app, ctx)
+ if (component) {
+ if (component.__VUE_DEVTOOLS_UID__ == null) {
+ component.__VUE_DEVTOOLS_UID__ = id
+ }
+ if (appRecord?.instanceMap) {
+ if (!appRecord.instanceMap.has(id)) {
+ appRecord.instanceMap.set(id, component)
+ }
+ }
+ }
+
+ if (parentUid != null && appRecord?.instanceMap) {
+ const parentInstances = await appRecord.backend.api.walkComponentParents(component)
+ if (parentInstances.length) {
+ // Check two parents level to update `hasChildren
+ for (let i = 0; i < parentInstances.length; i++) {
+ const parentId = await getComponentId(app, parentUid, parentInstances[i], ctx)
+ if (i < 2 && isSubscribed(BridgeSubscriptions.COMPONENT_TREE, parentId)) {
+ raf(() => {
+ sendComponentTreeData(appRecord, parentId, appRecord.componentFilter, null, false, ctx)
+ })
+ }
+
+ if (SharedData.trackUpdates) {
+ sendComponentUpdateTracking(parentId, now, ctx)
+ }
+ }
+ }
+ }
+
+ if (ctx.currentInspectedComponentId === id) {
+ await sendSelectedComponentData(appRecord, id, ctx)
+ }
+
+ if (SharedData.trackUpdates) {
+ sendComponentUpdateTracking(id, now, ctx)
+ }
+
+ if (SharedData.flashUpdates) {
+ await flashComponent(component, appRecord.backend)
+ }
+
+ await refreshComponentTreeSearch(ctx)
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+ })
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+ })
+
+ hook.on(HookEvents.COMPONENT_REMOVED, async (app, uid, parentUid, component) => {
+ try {
+ if (!app || (typeof uid !== 'number' && !uid) || !component) {
+ return
+ }
+ const id = await getComponentId(app, uid, component, ctx)
+
+ throttleQueue.add(`remove:${id}`, async () => {
+ try {
+ const appRecord = await getAppRecord(app, ctx)
+ if (parentUid != null && appRecord) {
+ const parentInstances = await appRecord.backend.api.walkComponentParents(component)
+ if (parentInstances.length) {
+ const parentId = await getComponentId(app, parentUid, parentInstances[0], ctx)
+ if (isSubscribed(BridgeSubscriptions.COMPONENT_TREE, parentId)) {
+ raf(async () => {
+ try {
+ const appRecord = await getAppRecord(app, ctx)
+
+ if (appRecord) {
+ sendComponentTreeData(appRecord, parentId, appRecord.componentFilter, null, false, ctx)
+ }
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+ })
+ }
+ }
+ }
+
+ if (isSubscribed(BridgeSubscriptions.SELECTED_COMPONENT_DATA, id)) {
+ await sendEmptyComponentData(id, ctx)
+ }
+
+ if (appRecord) {
+ appRecord.instanceMap.delete(id)
+ }
+
+ await refreshComponentTreeSearch(ctx)
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+ })
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+ })
+
+ hook.on(HookEvents.TRACK_UPDATE, (id, ctx) => {
+ sendComponentUpdateTracking(id, Date.now(), ctx)
+ })
+
+ hook.on(HookEvents.FLASH_UPDATE, (instance, backend) => {
+ flashComponent(instance, backend)
+ })
+
+ // Component perf
+
+ hook.on(HookEvents.PERFORMANCE_START, (app, uid, vm, type, time) => {
+ performanceMarkStart(app, uid, vm, type, time, ctx)
+ })
+
+ hook.on(HookEvents.PERFORMANCE_END, (app, uid, vm, type, time) => {
+ performanceMarkEnd(app, uid, vm, type, time, ctx)
+ })
+
+ // Highlighter
+
+ hook.on(HookEvents.COMPONENT_HIGHLIGHT, (instanceId) => {
+ highlight(ctx.currentAppRecord.instanceMap.get(instanceId), ctx.currentAppRecord.backend, ctx)
+ })
+
+ hook.on(HookEvents.COMPONENT_UNHIGHLIGHT, () => {
+ unHighlight()
+ })
+
+ // Timeline
+
+ setupTimeline(ctx)
+
+ hook.on(HookEvents.TIMELINE_LAYER_ADDED, async (options: TimelineLayerOptions, plugin: Plugin) => {
+ const appRecord = await getAppRecord(plugin.descriptor.app, ctx)
+ if (appRecord) {
+ ctx.timelineLayers.push({
+ ...options,
+ appRecord,
+ plugin,
+ events: [],
+ })
+ ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_LAYER_ADD, {})
+ }
+ })
+
+ hook.on(HookEvents.TIMELINE_EVENT_ADDED, async (options: TimelineEventOptions, plugin: Plugin) => {
+ await addTimelineEvent(options, plugin.descriptor.app, ctx)
+ })
+
+ // Custom inspectors
+
+ hook.on(HookEvents.CUSTOM_INSPECTOR_ADD, async (options: CustomInspectorOptions, plugin: Plugin) => {
+ const appRecord = await getAppRecord(plugin.descriptor.app, ctx)
+ if (appRecord) {
+ ctx.customInspectors.push({
+ ...options,
+ appRecord,
+ plugin,
+ treeFilter: '',
+ selectedNodeId: null,
+ })
+ ctx.bridge.send(BridgeEvents.TO_FRONT_CUSTOM_INSPECTOR_ADD, {})
+ }
+ })
+
+ hook.on(HookEvents.CUSTOM_INSPECTOR_SEND_TREE, async (inspectorId: string, plugin: Plugin) => {
+ const inspector = getInspector(inspectorId, plugin.descriptor.app, ctx)
+ if (inspector) {
+ await sendInspectorTree(inspector, ctx)
+ }
+ else if (SharedData.debugInfo) {
+ console.warn(`Inspector ${inspectorId} not found`)
+ }
+ })
+
+ hook.on(HookEvents.CUSTOM_INSPECTOR_SEND_STATE, async (inspectorId: string, plugin: Plugin) => {
+ const inspector = getInspector(inspectorId, plugin.descriptor.app, ctx)
+ if (inspector) {
+ await sendInspectorState(inspector, ctx)
+ }
+ else if (SharedData.debugInfo) {
+ console.warn(`Inspector ${inspectorId} not found`)
+ }
+ })
+
+ hook.on(HookEvents.CUSTOM_INSPECTOR_SELECT_NODE, async (inspectorId: string, nodeId: string, plugin: Plugin) => {
+ const inspector = getInspector(inspectorId, plugin.descriptor.app, ctx)
+ if (inspector) {
+ await selectInspectorNode(inspector, nodeId, ctx)
+ }
+ else if (SharedData.debugInfo) {
+ console.warn(`Inspector ${inspectorId} not found`)
+ }
+ })
+
+ // Plugins
+
+ try {
+ await addPreviouslyRegisteredPlugins(ctx)
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(`Error adding previously registered plugins:`)
+ console.error(e)
+ }
+ }
+ try {
+ await addQueuedPlugins(ctx)
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(`Error adding queued plugins:`)
+ console.error(e)
+ }
+ }
+
+ hook.on(HookEvents.SETUP_DEVTOOLS_PLUGIN, async (pluginDescriptor: PluginDescriptor, setupFn: SetupFunction) => {
+ await addPlugin({ pluginDescriptor, setupFn }, ctx)
+ })
+
+ target.__VUE_DEVTOOLS_PLUGIN_API_AVAILABLE__ = true
+
+ // Legacy flush
+
+ const handleFlush = debounce(async () => {
+ if (ctx.currentAppRecord?.backend.options.features.includes(BuiltinBackendFeature.FLUSH)) {
+ await sendComponentTreeData(ctx.currentAppRecord, '_root', ctx.currentAppRecord.componentFilter, null, false, ctx)
+ if (ctx.currentInspectedComponentId) {
+ await sendSelectedComponentData(ctx.currentAppRecord, ctx.currentInspectedComponentId, ctx)
+ }
+ }
+ }, 500)
+
+ hook.off(HookEvents.FLUSH)
+ hook.on(HookEvents.FLUSH, handleFlush)
+
+ // Connect done
+
+ try {
+ await addTimelineMarker({
+ id: 'vue-devtools-init-backend',
+ time: now(),
+ label: 'Vue Devtools connected',
+ color: 0x41B883,
+ all: true,
+ }, ctx)
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(`Error while adding devtools connected timeline marker:`)
+ console.error(e)
+ }
+ }
+}
+
+function connectBridge() {
+ // Subscriptions
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_SUBSCRIBE, ({ type, key }) => {
+ subscribe(type, key)
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_UNSUBSCRIBE, ({ type, key }) => {
+ unsubscribe(type, key)
+ })
+
+ // Tabs
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_TAB_SWITCH, async (tab) => {
+ ctx.currentTab = tab
+ await unHighlight()
+ })
+
+ // Apps
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_APP_LIST, async () => {
+ await sendApps(ctx)
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_APP_SELECT, async (id) => {
+ if (id == null) {
+ return
+ }
+ const record = ctx.appRecords.find(r => r.id === id)
+ if (record) {
+ await selectApp(record, ctx)
+ }
+ else if (SharedData.debugInfo) {
+ console.warn(`App with id ${id} not found`)
+ }
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_SCAN_LEGACY_APPS, () => {
+ if (hook.Vue) {
+ _legacy_getAndRegisterApps(ctx)
+ }
+ })
+
+ // Components
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_TREE, async ({ instanceId, filter, recursively }) => {
+ ctx.currentAppRecord.componentFilter = filter
+ subscribe(BridgeSubscriptions.COMPONENT_TREE, instanceId)
+ await sendComponentTreeData(ctx.currentAppRecord, instanceId, filter, null, recursively, ctx)
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_SELECTED_DATA, async (instanceId) => {
+ await sendSelectedComponentData(ctx.currentAppRecord, instanceId, ctx)
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_EDIT_STATE, async ({ instanceId, dotPath, type, value, newKey, remove }) => {
+ await editComponentState(instanceId, dotPath, type, { value, newKey, remove }, ctx)
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_INSPECT_DOM, async ({ instanceId }) => {
+ const instance = getComponentInstance(ctx.currentAppRecord, instanceId, ctx)
+ if (instance) {
+ const [el] = await ctx.currentAppRecord.backend.api.getComponentRootElements(instance)
+ if (el) {
+ target.__VUE_DEVTOOLS_INSPECT_TARGET__ = el
+ ctx.bridge.send(BridgeEvents.TO_FRONT_COMPONENT_INSPECT_DOM, null)
+ }
+ }
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_SCROLL_TO, async ({ instanceId }) => {
+ if (!isBrowser) {
+ return
+ }
+ const instance = getComponentInstance(ctx.currentAppRecord, instanceId, ctx)
+ if (instance) {
+ const [el] = await ctx.currentAppRecord.backend.api.getComponentRootElements(instance)
+ if (el) {
+ if (typeof el.scrollIntoView === 'function') {
+ el.scrollIntoView({
+ behavior: 'smooth',
+ block: 'center',
+ inline: 'center',
+ })
+ }
+ else {
+ // Handle nodes that don't implement scrollIntoView
+ const bounds = await ctx.currentAppRecord.backend.api.getComponentBounds(instance)
+ const scrollTarget = document.createElement('div')
+ scrollTarget.style.position = 'absolute'
+ scrollTarget.style.width = `${bounds.width}px`
+ scrollTarget.style.height = `${bounds.height}px`
+ scrollTarget.style.top = `${bounds.top}px`
+ scrollTarget.style.left = `${bounds.left}px`
+ document.body.appendChild(scrollTarget)
+ scrollTarget.scrollIntoView({
+ behavior: 'smooth',
+ block: 'center',
+ inline: 'center',
+ })
+ setTimeout(() => {
+ document.body.removeChild(scrollTarget)
+ }, 2000)
+ }
+ highlight(instance, ctx.currentAppRecord.backend, ctx)
+ setTimeout(() => {
+ unHighlight()
+ }, 2000)
+ }
+ }
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_RENDER_CODE, async ({ instanceId }) => {
+ if (!isBrowser) {
+ return
+ }
+ const instance = getComponentInstance(ctx.currentAppRecord, instanceId, ctx)
+ if (instance) {
+ const { code } = await ctx.currentAppRecord.backend.api.getComponentRenderCode(instance)
+ ctx.bridge.send(BridgeEvents.TO_FRONT_COMPONENT_RENDER_CODE, {
+ instanceId,
+ code,
+ })
+ }
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_CUSTOM_STATE_ACTION, async ({ value, actionIndex }) => {
+ const rawAction = value._custom.actions[actionIndex]
+ const action = revive(rawAction?.action)
+ if (action) {
+ try {
+ await action()
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+ }
+ else if (SharedData.debugInfo) {
+ console.warn(`Couldn't revive action ${actionIndex} from`, value)
+ }
+ })
+
+ // Highlighter
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_MOUSE_OVER, async (instanceId) => {
+ await highlight(ctx.currentAppRecord.instanceMap.get(instanceId), ctx.currentAppRecord.backend, ctx)
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_MOUSE_OUT, async () => {
+ await unHighlight()
+ })
+
+ // Component picker
+
+ const componentPicker = new ComponentPicker(ctx)
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_PICK, () => {
+ componentPicker.startSelecting()
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_COMPONENT_PICK_CANCELED, () => {
+ componentPicker.stopSelecting()
+ })
+
+ // Timeline
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_LAYER_LIST, async () => {
+ await sendTimelineLayers(ctx)
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_SHOW_SCREENSHOT, async ({ screenshot }) => {
+ await showScreenshot(screenshot, ctx)
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_CLEAR, async () => {
+ await clearTimeline(ctx)
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_EVENT_DATA, async ({ id }) => {
+ await sendTimelineEventData(id, ctx)
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_LAYER_LOAD_EVENTS, async ({ appId, layerId }) => {
+ await sendTimelineLayerEvents(appId, layerId, ctx)
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_LOAD_MARKERS, async () => {
+ await sendTimelineMarkers(ctx)
+ })
+
+ // Custom inspectors
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_CUSTOM_INSPECTOR_LIST, async () => {
+ await sendCustomInspectors(ctx)
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_CUSTOM_INSPECTOR_TREE, async ({ inspectorId, appId, treeFilter }) => {
+ const inspector = await getInspectorWithAppId(inspectorId, appId, ctx)
+ if (inspector) {
+ inspector.treeFilter = treeFilter
+ sendInspectorTree(inspector, ctx)
+ }
+ else if (SharedData.debugInfo) {
+ console.warn(`Inspector ${inspectorId} not found`)
+ }
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_CUSTOM_INSPECTOR_STATE, async ({ inspectorId, appId, nodeId }) => {
+ const inspector = await getInspectorWithAppId(inspectorId, appId, ctx)
+ if (inspector) {
+ inspector.selectedNodeId = nodeId
+ sendInspectorState(inspector, ctx)
+ }
+ else if (SharedData.debugInfo) {
+ console.warn(`Inspector ${inspectorId} not found`)
+ }
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_CUSTOM_INSPECTOR_EDIT_STATE, async ({ inspectorId, appId, nodeId, path, type, payload }) => {
+ const inspector = await getInspectorWithAppId(inspectorId, appId, ctx)
+ if (inspector) {
+ await editInspectorState(inspector, nodeId, path, type, payload, ctx)
+ inspector.selectedNodeId = nodeId
+ await sendInspectorState(inspector, ctx)
+ }
+ else if (SharedData.debugInfo) {
+ console.warn(`Inspector ${inspectorId} not found`)
+ }
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_CUSTOM_INSPECTOR_ACTION, async ({ inspectorId, appId, actionIndex, actionType, args }) => {
+ const inspector = await getInspectorWithAppId(inspectorId, appId, ctx)
+ if (inspector) {
+ const action = inspector[actionType ?? 'actions'][actionIndex]
+ try {
+ await action.action(...(args ?? []))
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+ }
+ else if (SharedData.debugInfo) {
+ console.warn(`Inspector ${inspectorId} not found`)
+ }
+ })
+
+ // Misc
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_LOG, (payload: { level: string, value: any, serialized?: boolean, revive?: boolean }) => {
+ let value = payload.value
+ if (payload.serialized) {
+ value = parse(value, payload.revive)
+ }
+ else if (payload.revive) {
+ value = revive(value)
+ }
+ // eslint-disable-next-line no-console
+ console[payload.level](value)
+ })
+
+ // Plugins
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_DEVTOOLS_PLUGIN_LIST, async () => {
+ await sendPluginList(ctx)
+ })
+
+ ctx.bridge.on(BridgeEvents.TO_BACK_DEVTOOLS_PLUGIN_SETTING_UPDATED, ({ pluginId, key, newValue, oldValue }) => {
+ const settings = getPluginSettings(pluginId)
+ ctx.hook.emit(HookEvents.PLUGIN_SETTINGS_SET, pluginId, settings)
+ ctx.currentAppRecord.backend.api.callHook(Hooks.SET_PLUGIN_SETTINGS, {
+ app: ctx.currentAppRecord.options.app,
+ pluginId,
+ key,
+ newValue,
+ oldValue,
+ settings,
+ })
+ })
+
+ ctx.bridge.send(BridgeEvents.TO_FRONT_TITLE, { title: document.title })
+ // Watch page title
+ const titleEl = document.querySelector('title')
+ if (titleEl && typeof MutationObserver !== 'undefined') {
+ if (pageTitleObserver) {
+ pageTitleObserver.disconnect()
+ }
+ pageTitleObserver = new MutationObserver((mutations) => {
+ const title = mutations[0].target as HTMLTitleElement
+ ctx.bridge.send(BridgeEvents.TO_FRONT_TITLE, { title: title.textContent })
+ })
+ pageTitleObserver.observe(titleEl, { subtree: true, characterData: true, childList: true })
+ }
+}
diff --git a/vue-devtools/packages/app-backend-core/src/inspector.ts b/vue-devtools/packages/app-backend-core/src/inspector.ts
new file mode 100644
index 0000000000000000000000000000000000000000..67e79a3838c996bb14496d876f96059db94eb757
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/inspector.ts
@@ -0,0 +1,76 @@
+import type { App } from '@vue/devtools-api'
+import type { BackendContext, CustomInspector } from '@vue-devtools/app-backend-api'
+import { BridgeEvents, parse, stringify } from '@vue-devtools/shared-utils'
+
+export function getInspector(inspectorId: string, app: App, ctx: BackendContext) {
+ return ctx.customInspectors.find(i => i.id === inspectorId && i.appRecord.options.app === app)
+}
+
+export async function getInspectorWithAppId(inspectorId: string, appId: string, ctx: BackendContext): Promise {
+ for (const i of ctx.customInspectors) {
+ if (i.id === inspectorId && i.appRecord.id === appId) {
+ return i
+ }
+ }
+ return null
+}
+
+export async function sendInspectorTree(inspector: CustomInspector, ctx: BackendContext) {
+ const rootNodes = await inspector.appRecord.backend.api.getInspectorTree(inspector.id, inspector.appRecord.options.app, inspector.treeFilter)
+ ctx.bridge.send(BridgeEvents.TO_FRONT_CUSTOM_INSPECTOR_TREE, {
+ appId: inspector.appRecord.id,
+ inspectorId: inspector.id,
+ rootNodes,
+ })
+}
+
+export async function sendInspectorState(inspector: CustomInspector, ctx: BackendContext) {
+ const state = inspector.selectedNodeId ? await inspector.appRecord.backend.api.getInspectorState(inspector.id, inspector.appRecord.options.app, inspector.selectedNodeId) : null
+ ctx.bridge.send(BridgeEvents.TO_FRONT_CUSTOM_INSPECTOR_STATE, {
+ appId: inspector.appRecord.id,
+ inspectorId: inspector.id,
+ state: stringify(state),
+ })
+}
+
+export async function editInspectorState(inspector: CustomInspector, nodeId: string, dotPath: string, type: string, state: any, _ctx: BackendContext) {
+ await inspector.appRecord.backend.api.editInspectorState(inspector.id, inspector.appRecord.options.app, nodeId, dotPath, type, {
+ ...state,
+ value: state.value != null ? parse(state.value, true) : state.value,
+ })
+}
+
+export async function sendCustomInspectors(ctx: BackendContext) {
+ const inspectors = []
+ for (const i of ctx.customInspectors) {
+ inspectors.push({
+ id: i.id,
+ appId: i.appRecord.id,
+ pluginId: i.plugin.descriptor.id,
+ label: i.label,
+ icon: i.icon,
+ treeFilterPlaceholder: i.treeFilterPlaceholder,
+ stateFilterPlaceholder: i.stateFilterPlaceholder,
+ noSelectionText: i.noSelectionText,
+ actions: i.actions?.map(a => ({
+ icon: a.icon,
+ tooltip: a.tooltip,
+ })),
+ nodeActions: i.nodeActions?.map(a => ({
+ icon: a.icon,
+ tooltip: a.tooltip,
+ })),
+ })
+ }
+ ctx.bridge.send(BridgeEvents.TO_FRONT_CUSTOM_INSPECTOR_LIST, {
+ inspectors,
+ })
+}
+
+export async function selectInspectorNode(inspector: CustomInspector, nodeId: string, ctx: BackendContext) {
+ ctx.bridge.send(BridgeEvents.TO_FRONT_CUSTOM_INSPECTOR_SELECT_NODE, {
+ appId: inspector.appRecord.id,
+ inspectorId: inspector.id,
+ nodeId,
+ })
+}
diff --git a/vue-devtools/packages/app-backend-core/src/legacy/scan.ts b/vue-devtools/packages/app-backend-core/src/legacy/scan.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7d4428744efd8a65959c7ca3476c8f1497b0eff0
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/legacy/scan.ts
@@ -0,0 +1,108 @@
+import { isBrowser, target } from '@vue-devtools/shared-utils'
+import { getPageConfig } from '../page-config'
+
+const rootInstances = []
+
+/**
+ * Scan the page for root level Vue instances.
+ */
+export function scan() {
+ rootInstances.length = 0
+
+ let inFragment = false
+ let currentFragment = null
+
+ function processInstance(instance) {
+ if (instance) {
+ if (!rootInstances.includes(instance.$root)) {
+ instance = instance.$root
+ }
+ if (instance._isFragment) {
+ inFragment = true
+ currentFragment = instance
+ }
+
+ // respect Vue.config.devtools option
+ let baseVue = instance.constructor
+ while (baseVue.super) {
+ baseVue = baseVue.super
+ }
+ if (baseVue.config && baseVue.config.devtools) {
+ rootInstances.push(instance)
+ }
+
+ return true
+ }
+ }
+
+ if (isBrowser) {
+ const walkDocument = (document) => {
+ walk(document, (node) => {
+ if (inFragment) {
+ if (node === currentFragment._fragmentEnd) {
+ inFragment = false
+ currentFragment = null
+ }
+ return true
+ }
+ const instance = node.__vue__
+
+ return processInstance(instance)
+ })
+ }
+ walkDocument(document)
+
+ const iframes = document.querySelectorAll('iframe')
+ for (const iframe of iframes) {
+ try {
+ walkDocument(iframe.contentDocument)
+ }
+ catch (e) {
+ // Ignore
+ }
+ }
+
+ // Scan for Vue instances in the customTarget elements
+ const { customVue2ScanSelector } = getPageConfig()
+ const customTargets = customVue2ScanSelector ? document.querySelectorAll(customVue2ScanSelector) : []
+ for (const customTarget of customTargets) {
+ try {
+ walkDocument(customTarget)
+ }
+ catch (e) {
+ // Ignore
+ }
+ }
+ }
+ else {
+ if (Array.isArray(target.__VUE_ROOT_INSTANCES__)) {
+ target.__VUE_ROOT_INSTANCES__.map(processInstance)
+ }
+ }
+
+ return rootInstances
+}
+
+/**
+ * DOM walk helper
+ *
+ * @param {NodeList} nodes
+ * @param {Function} fn
+ */
+
+function walk(node, fn) {
+ if (node.childNodes) {
+ for (let i = 0, l = node.childNodes.length; i < l; i++) {
+ const child = node.childNodes[i]
+ const stop = fn(child)
+ if (!stop) {
+ walk(child, fn)
+ }
+ }
+ }
+
+ // also walk shadow DOM
+ if (node.shadowRoot) {
+ walk(node.shadowRoot, fn)
+ }
+}
diff --git a/vue-devtools/packages/app-backend-core/src/page-config.ts b/vue-devtools/packages/app-backend-core/src/page-config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d570ae97f80fc05ff051871843f938c30fdc3a0c
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/page-config.ts
@@ -0,0 +1,25 @@
+import { SharedData, target } from '@vue-devtools/shared-utils'
+
+export interface PageConfig {
+ openInEditorHost?: string
+ defaultSelectedAppId?: string
+ customVue2ScanSelector?: string
+}
+
+let config: PageConfig = {}
+
+export function getPageConfig(): PageConfig {
+ return config
+}
+
+export function initOnPageConfig() {
+ // User project devtools config
+ if (Object.hasOwnProperty.call(target, 'VUE_DEVTOOLS_CONFIG')) {
+ config = SharedData.pageConfig = target.VUE_DEVTOOLS_CONFIG
+
+ // Open in editor
+ if (Object.hasOwnProperty.call(config, 'openInEditorHost')) {
+ SharedData.openInEditorHost = config.openInEditorHost
+ }
+ }
+}
diff --git a/vue-devtools/packages/app-backend-core/src/perf.ts b/vue-devtools/packages/app-backend-core/src/perf.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4cfa2f03c201c65b3a996eb28379c051bdd907a8
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/perf.ts
@@ -0,0 +1,192 @@
+import type { BackendContext, DevtoolsBackend } from '@vue-devtools/app-backend-api'
+import type { App, ComponentInstance } from '@vue/devtools-api'
+import { BridgeSubscriptions, SharedData, raf } from '@vue-devtools/shared-utils'
+import { addTimelineEvent } from './timeline'
+import { getAppRecord } from './app'
+import { getComponentId, sendComponentTreeData } from './component'
+import { isSubscribed } from './util/subscriptions'
+
+const markEndQueue = new Map()
+
+export async function performanceMarkStart(
+ app: App,
+ uid: number,
+ instance: ComponentInstance,
+ type: string,
+ time: number,
+ ctx: BackendContext,
+) {
+ try {
+ if (!SharedData.performanceMonitoringEnabled) {
+ return
+ }
+ const appRecord = await getAppRecord(app, ctx)
+ if (!appRecord) {
+ return
+ }
+ const componentName = await appRecord.backend.api.getComponentName(instance)
+ const groupId = ctx.perfUniqueGroupId++
+ const groupKey = `${uid}-${type}`
+ appRecord.perfGroupIds.set(groupKey, { groupId, time })
+ await addTimelineEvent({
+ layerId: 'performance',
+ event: {
+ time,
+ data: {
+ component: componentName,
+ type,
+ measure: 'start',
+ },
+ title: componentName,
+ subtitle: type,
+ groupId,
+ },
+ }, app, ctx)
+
+ if (markEndQueue.has(groupKey)) {
+ const {
+ app,
+ uid,
+ instance,
+ type,
+ time,
+ } = markEndQueue.get(groupKey)
+ markEndQueue.delete(groupKey)
+ await performanceMarkEnd(
+ app,
+ uid,
+ instance,
+ type,
+ time,
+ ctx,
+ )
+ }
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+}
+
+export async function performanceMarkEnd(
+ app: App,
+ uid: number,
+ instance: ComponentInstance,
+ type: string,
+ time: number,
+ ctx: BackendContext,
+) {
+ try {
+ if (!SharedData.performanceMonitoringEnabled) {
+ return
+ }
+ const appRecord = await getAppRecord(app, ctx)
+ if (!appRecord) {
+ return
+ }
+ const componentName = await appRecord.backend.api.getComponentName(instance)
+ const groupKey = `${uid}-${type}`
+ const groupInfo = appRecord.perfGroupIds.get(groupKey)
+ if (!groupInfo) {
+ markEndQueue.set(groupKey, {
+ app,
+ uid,
+ instance,
+ type,
+ time,
+ })
+ return
+ }
+ const { groupId, time: startTime } = groupInfo
+ const duration = time - startTime
+ await addTimelineEvent({
+ layerId: 'performance',
+ event: {
+ time,
+ data: {
+ component: componentName,
+ type,
+ measure: 'end',
+ duration: {
+ _custom: {
+ type: 'Duration',
+ value: duration,
+ display: `${duration} ms`,
+ },
+ },
+ },
+ title: componentName,
+ subtitle: type,
+ groupId,
+ },
+ }, app, ctx)
+
+ // Mark on component
+ const tooSlow = duration > 10
+ if (tooSlow || instance.__VUE_DEVTOOLS_SLOW__) {
+ let change = false
+ if (tooSlow && !instance.__VUE_DEVTOOLS_SLOW__) {
+ instance.__VUE_DEVTOOLS_SLOW__ = {
+ duration: null,
+ measures: {},
+ }
+ }
+
+ const data = instance.__VUE_DEVTOOLS_SLOW__
+
+ if (tooSlow && (data.duration == null || data.duration < duration)) {
+ data.duration = duration
+ change = true
+ }
+
+ if (data.measures[type] == null || data.measures[type] < duration) {
+ data.measures[type] = duration
+ change = true
+ }
+
+ if (change) {
+ // Update component tree
+ const id = await getComponentId(app, uid, instance, ctx)
+ if (isSubscribed(BridgeSubscriptions.COMPONENT_TREE, id)) {
+ raf(() => {
+ sendComponentTreeData(appRecord, id, ctx.currentAppRecord.componentFilter, null, false, ctx)
+ })
+ }
+ }
+ }
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+}
+
+export function handleAddPerformanceTag(backend: DevtoolsBackend, _ctx: BackendContext) {
+ backend.api.on.visitComponentTree((payload) => {
+ if (payload.componentInstance.__VUE_DEVTOOLS_SLOW__) {
+ const { duration, measures } = payload.componentInstance.__VUE_DEVTOOLS_SLOW__
+
+ let tooltip = ''
+ for (const type in measures) {
+ const d = measures[type]
+ tooltip += `
${type}
${Math.round(d * 1000) / 1000} ms
`
+ }
+ tooltip += '
'
+
+ payload.treeNode.tags.push({
+ backgroundColor: duration > 30 ? 0xF87171 : 0xFBBF24,
+ textColor: 0x000000,
+ label: `${Math.round(duration * 1000) / 1000} ms`,
+ tooltip,
+ })
+ }
+ })
+}
diff --git a/vue-devtools/packages/app-backend-core/src/plugin.ts b/vue-devtools/packages/app-backend-core/src/plugin.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cf726df92659fffd51a826cabd23c3d8f2d45c56
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/plugin.ts
@@ -0,0 +1,82 @@
+import type { PluginQueueItem } from '@vue/devtools-api'
+import type { BackendContext, Plugin } from '@vue-devtools/app-backend-api'
+import { DevtoolsPluginApiInstance } from '@vue-devtools/app-backend-api'
+import { BridgeEvents, SharedData, target } from '@vue-devtools/shared-utils'
+import { getAppRecord, getAppRecordId } from './app'
+
+export async function addPlugin(pluginQueueItem: PluginQueueItem, ctx: BackendContext) {
+ const { pluginDescriptor, setupFn } = pluginQueueItem
+
+ const plugin: Plugin = {
+ descriptor: pluginDescriptor,
+ setupFn,
+ error: null,
+ }
+ ctx.currentPlugin = plugin
+ try {
+ const appRecord = await getAppRecord(plugin.descriptor.app, ctx)
+ if (!appRecord) {
+ return
+ }
+ const api = new DevtoolsPluginApiInstance(plugin, appRecord, ctx)
+ if (pluginQueueItem.proxy) {
+ await pluginQueueItem.proxy.setRealTarget(api)
+ }
+ else {
+ setupFn(api)
+ }
+ }
+ catch (e) {
+ plugin.error = e
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+ ctx.currentPlugin = null
+ ctx.plugins.push(plugin)
+ ctx.bridge.send(BridgeEvents.TO_FRONT_DEVTOOLS_PLUGIN_ADD, {
+ plugin: await serializePlugin(plugin),
+ })
+
+ const targetList = target.__VUE_DEVTOOLS_REGISTERED_PLUGINS__ = target.__VUE_DEVTOOLS_REGISTERED_PLUGINS__ || []
+ targetList.push({
+ pluginDescriptor,
+ setupFn,
+ })
+}
+
+export async function addQueuedPlugins(ctx: BackendContext) {
+ if (target.__VUE_DEVTOOLS_PLUGINS__ && Array.isArray(target.__VUE_DEVTOOLS_PLUGINS__)) {
+ for (const queueItem of target.__VUE_DEVTOOLS_PLUGINS__) {
+ await addPlugin(queueItem, ctx)
+ }
+ target.__VUE_DEVTOOLS_PLUGINS__ = null
+ }
+}
+
+export async function addPreviouslyRegisteredPlugins(ctx: BackendContext) {
+ if (target.__VUE_DEVTOOLS_REGISTERED_PLUGINS__ && Array.isArray(target.__VUE_DEVTOOLS_REGISTERED_PLUGINS__)) {
+ for (const queueItem of target.__VUE_DEVTOOLS_REGISTERED_PLUGINS__) {
+ await addPlugin(queueItem, ctx)
+ }
+ }
+}
+
+export async function sendPluginList(ctx: BackendContext) {
+ ctx.bridge.send(BridgeEvents.TO_FRONT_DEVTOOLS_PLUGIN_LIST, {
+ plugins: await Promise.all(ctx.plugins.map(p => serializePlugin(p))),
+ })
+}
+
+export async function serializePlugin(plugin: Plugin) {
+ return {
+ id: plugin.descriptor.id,
+ label: plugin.descriptor.label,
+ appId: getAppRecordId(plugin.descriptor.app),
+ packageName: plugin.descriptor.packageName,
+ homepage: plugin.descriptor.homepage,
+ logo: plugin.descriptor.logo,
+ componentStateTypes: plugin.descriptor.componentStateTypes,
+ settingsSchema: plugin.descriptor.settings,
+ }
+}
diff --git a/vue-devtools/packages/app-backend-core/src/timeline-builtins.ts b/vue-devtools/packages/app-backend-core/src/timeline-builtins.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9b365c9c5e0b4982c5380e83ee738868399b1d1f
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/timeline-builtins.ts
@@ -0,0 +1,102 @@
+import type { TimelineLayerOptions } from '@vue/devtools-api'
+
+export const builtinLayers: TimelineLayerOptions[] = [
+ {
+ id: 'mouse',
+ label: 'Mouse',
+ color: 0xA451AF,
+ screenshotOverlayRender(event, { events }) {
+ const samePositionEvent = events.find(e => e !== event && e.renderMeta.textEl && e.data.x === event.data.x && e.data.y === event.data.y)
+ if (samePositionEvent) {
+ const text = document.createElement('div')
+ text.textContent = event.data.type
+ samePositionEvent.renderMeta.textEl.appendChild(text)
+ return false
+ }
+
+ const div = document.createElement('div')
+ div.style.position = 'absolute'
+ div.style.left = `${event.data.x - 4}px`
+ div.style.top = `${event.data.y - 4}px`
+ div.style.width = '8px'
+ div.style.height = '8px'
+ div.style.borderRadius = '100%'
+ div.style.backgroundColor = 'rgba(164, 81, 175, 0.5)'
+
+ const text = document.createElement('div')
+ text.textContent = event.data.type
+ text.style.color = '#541e5b'
+ text.style.fontFamily = 'monospace'
+ text.style.fontSize = '9px'
+ text.style.position = 'absolute'
+ text.style.left = '10px'
+ text.style.top = '10px'
+ text.style.padding = '1px'
+ text.style.backgroundColor = 'rgba(255, 255, 255, 0.9)'
+ text.style.borderRadius = '3px'
+ div.appendChild(text)
+
+ event.renderMeta.textEl = text
+
+ return div
+ },
+ },
+ {
+ id: 'keyboard',
+ label: 'Keyboard',
+ color: 0x8151AF,
+ },
+ {
+ id: 'component-event',
+ label: 'Component events',
+ color: 0x41B883,
+ screenshotOverlayRender: (event, { events }) => {
+ if (!event.meta.bounds || events.some(e => e !== event && e.layerId === event.layerId && e.renderMeta.drawn && (e.meta.componentId === event.meta.componentId || (
+ e.meta.bounds.left === event.meta.bounds.left
+ && e.meta.bounds.top === event.meta.bounds.top
+ && e.meta.bounds.width === event.meta.bounds.width
+ && e.meta.bounds.height === event.meta.bounds.height
+ )))) {
+ return false
+ }
+
+ const div = document.createElement('div')
+ div.style.position = 'absolute'
+ div.style.left = `${event.meta.bounds.left - 4}px`
+ div.style.top = `${event.meta.bounds.top - 4}px`
+ div.style.width = `${event.meta.bounds.width}px`
+ div.style.height = `${event.meta.bounds.height}px`
+ div.style.borderRadius = '8px'
+ div.style.borderStyle = 'solid'
+ div.style.borderWidth = '4px'
+ div.style.borderColor = 'rgba(65, 184, 131, 0.5)'
+ div.style.textAlign = 'center'
+ div.style.display = 'flex'
+ div.style.alignItems = 'center'
+ div.style.justifyContent = 'center'
+ div.style.overflow = 'hidden'
+
+ const text = document.createElement('div')
+ text.style.color = '#267753'
+ text.style.fontFamily = 'monospace'
+ text.style.fontSize = '9px'
+ text.style.padding = '1px'
+ text.style.backgroundColor = 'rgba(255, 255, 255, 0.9)'
+ text.style.borderRadius = '3px'
+ text.textContent = event.data.event
+ div.appendChild(text)
+
+ event.renderMeta.drawn = true
+
+ return div
+ },
+ },
+ {
+ id: 'performance',
+ label: 'Performance',
+ color: 0x41B86A,
+ groupsOnly: true,
+ skipScreenshots: true,
+ ignoreNoDurationGroups: true,
+ },
+]
diff --git a/vue-devtools/packages/app-backend-core/src/timeline-marker.ts b/vue-devtools/packages/app-backend-core/src/timeline-marker.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8ac048e27fedb55ea9e9ab0691e4b93e5fbd1a29
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/timeline-marker.ts
@@ -0,0 +1,56 @@
+import type { BackendContext, TimelineMarker } from '@vue-devtools/app-backend-api'
+import { BridgeEvents, SharedData } from '@vue-devtools/shared-utils'
+import type { TimelineMarkerOptions } from '@vue/devtools-api'
+import { isPerformanceSupported } from '@vue/devtools-api'
+import { dateThreshold, perfTimeDiff } from './timeline'
+
+export async function addTimelineMarker(options: TimelineMarkerOptions, ctx: BackendContext) {
+ if (!SharedData.timelineRecording) {
+ return
+ }
+ if (!ctx.currentAppRecord) {
+ options.all = true
+ }
+ const marker: TimelineMarker = {
+ ...options,
+ appRecord: options.all ? null : ctx.currentAppRecord,
+ }
+ ctx.timelineMarkers.push(marker)
+ ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_MARKER, {
+ marker: await serializeMarker(marker),
+ appId: ctx.currentAppRecord?.id,
+ })
+}
+
+export async function sendTimelineMarkers(ctx: BackendContext) {
+ if (!SharedData.timelineRecording) {
+ return
+ }
+ if (!ctx.currentAppRecord) {
+ return
+ }
+ const markers = ctx.timelineMarkers.filter(marker => marker.all || marker.appRecord === ctx.currentAppRecord)
+ const result = []
+ for (const marker of markers) {
+ result.push(await serializeMarker(marker))
+ }
+ ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_LOAD_MARKERS, {
+ markers: result,
+ appId: ctx.currentAppRecord.id,
+ })
+}
+
+async function serializeMarker(marker: TimelineMarker) {
+ let time = marker.time
+ if (isPerformanceSupported() && time < dateThreshold) {
+ time += perfTimeDiff
+ }
+ return {
+ id: marker.id,
+ appId: marker.appRecord?.id,
+ all: marker.all,
+ time: Math.round(time * 1000),
+ label: marker.label,
+ color: marker.color,
+ }
+}
diff --git a/vue-devtools/packages/app-backend-core/src/timeline-screenshot.ts b/vue-devtools/packages/app-backend-core/src/timeline-screenshot.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1b11a5f713fc0205d5a893459189f1267b87d1d4
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/timeline-screenshot.ts
@@ -0,0 +1,129 @@
+import type { BackendContext } from '@vue-devtools/app-backend-api'
+import type { ID, ScreenshotOverlayRenderContext } from '@vue/devtools-api'
+import { SharedData } from '@vue-devtools/shared-utils'
+import { JobQueue } from './util/queue'
+import { builtinLayers } from './timeline-builtins'
+
+let overlay: HTMLDivElement
+let image: HTMLImageElement
+let container: HTMLDivElement
+
+const jobQueue = new JobQueue()
+
+interface Screenshot {
+ id: ID
+ time: number
+ image: string
+ events: ID[]
+}
+
+export async function showScreenshot(screenshot: Screenshot, ctx: BackendContext) {
+ await jobQueue.queue('showScreenshot', async () => {
+ if (screenshot) {
+ if (!container) {
+ createElements()
+ }
+
+ image.src = screenshot.image
+ image.style.visibility = screenshot.image ? 'visible' : 'hidden'
+
+ clearContent()
+
+ const events = screenshot.events.map(id => ctx.timelineEventMap.get(id)).filter(Boolean).map(eventData => ({
+ layer: builtinLayers.concat(ctx.timelineLayers).find(layer => layer.id === eventData.layerId),
+ event: {
+ ...eventData.event,
+ layerId: eventData.layerId,
+ renderMeta: {},
+ },
+ }))
+
+ const renderContext: ScreenshotOverlayRenderContext = {
+ screenshot,
+ events: events.map(({ event }) => event),
+ index: 0,
+ }
+
+ for (let i = 0; i < events.length; i++) {
+ const { layer, event } = events[i]
+ if (layer.screenshotOverlayRender) {
+ renderContext.index = i
+ try {
+ const result = await layer.screenshotOverlayRender(event, renderContext)
+ if (result !== false) {
+ if (typeof result === 'string') {
+ container.innerHTML += result
+ }
+ else {
+ container.appendChild(result)
+ }
+ }
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+ }
+ }
+
+ showElement()
+ }
+ else {
+ hideElement()
+ }
+ })
+}
+
+function createElements() {
+ overlay = document.createElement('div')
+ overlay.style.position = 'fixed'
+ overlay.style.zIndex = '9999999999999'
+ overlay.style.pointerEvents = 'none'
+ overlay.style.left = '0'
+ overlay.style.top = '0'
+ overlay.style.width = '100vw'
+ overlay.style.height = '100vh'
+ overlay.style.backgroundColor = 'rgba(0,0,0,0.5)'
+ overlay.style.overflow = 'hidden'
+
+ const imageBox = document.createElement('div')
+ imageBox.style.position = 'relative'
+ overlay.appendChild(imageBox)
+
+ image = document.createElement('img')
+ imageBox.appendChild(image)
+
+ container = document.createElement('div')
+ container.style.position = 'absolute'
+ container.style.left = '0'
+ container.style.top = '0'
+ imageBox.appendChild(container)
+
+ const style = document.createElement('style')
+ style.innerHTML = '.__vuedevtools_no-scroll { overflow: hidden; }'
+ document.head.appendChild(style)
+}
+
+function showElement() {
+ if (!overlay.parentNode) {
+ document.body.appendChild(overlay)
+ document.body.classList.add('__vuedevtools_no-scroll')
+ }
+}
+
+function hideElement() {
+ if (overlay && overlay.parentNode) {
+ overlay.parentNode.removeChild(overlay)
+
+ document.body.classList.remove('__vuedevtools_no-scroll')
+
+ clearContent()
+ }
+}
+
+function clearContent() {
+ while (container.firstChild) {
+ container.removeChild(container.lastChild)
+ }
+}
diff --git a/vue-devtools/packages/app-backend-core/src/timeline.ts b/vue-devtools/packages/app-backend-core/src/timeline.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b67b58eebb72894708e790090b25a4a37dc6c90b
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/timeline.ts
@@ -0,0 +1,249 @@
+import type { AppRecord, BackendContext } from '@vue-devtools/app-backend-api'
+import { BridgeEvents, HookEvents, SharedData, isBrowser, stringify } from '@vue-devtools/shared-utils'
+import type { App, ID, TimelineEventOptions, WithId } from '@vue/devtools-api'
+import { isPerformanceSupported, now } from '@vue/devtools-api'
+import { hook } from './global-hook'
+import { getAppRecord, getAppRecordId } from './app'
+import { builtinLayers } from './timeline-builtins'
+
+export function setupTimeline(ctx: BackendContext) {
+ setupBuiltinLayers(ctx)
+}
+
+export function addBuiltinLayers(appRecord: AppRecord, ctx: BackendContext) {
+ for (const layerDef of builtinLayers) {
+ ctx.timelineLayers.push({
+ ...layerDef,
+ appRecord,
+ plugin: null,
+ events: [],
+ })
+ }
+}
+
+function setupBuiltinLayers(ctx: BackendContext) {
+ if (isBrowser) {
+ (['mousedown', 'mouseup', 'click', 'dblclick'] as const).forEach((eventType) => {
+ window.addEventListener(eventType, async (event: MouseEvent) => {
+ await addTimelineEvent({
+ layerId: 'mouse',
+ event: {
+ time: now(),
+ data: {
+ type: eventType,
+ x: event.clientX,
+ y: event.clientY,
+ },
+ title: eventType,
+ },
+ }, null, ctx)
+ }, {
+ capture: true,
+ passive: true,
+ })
+ })
+
+ ;(['keyup', 'keydown', 'keypress'] as const).forEach((eventType) => {
+ window.addEventListener(eventType, async (event: KeyboardEvent) => {
+ await addTimelineEvent({
+ layerId: 'keyboard',
+ event: {
+ time: now(),
+ data: {
+ type: eventType,
+ key: event.key,
+ ctrlKey: event.ctrlKey,
+ shiftKey: event.shiftKey,
+ altKey: event.altKey,
+ metaKey: event.metaKey,
+ },
+ title: event.key,
+ },
+ }, null, ctx)
+ }, {
+ capture: true,
+ passive: true,
+ })
+ })
+ }
+
+ hook.on(HookEvents.COMPONENT_EMIT, async (app, instance, event, params) => {
+ try {
+ if (!SharedData.componentEventsEnabled) {
+ return
+ }
+
+ const appRecord = await getAppRecord(app, ctx)
+ if (!appRecord) {
+ return
+ }
+ const componentId = `${appRecord.id}:${instance.uid}`
+ const componentDisplay = (await appRecord.backend.api.getComponentName(instance)) || 'Unknown Component'
+
+ await addTimelineEvent({
+ layerId: 'component-event',
+ event: {
+ time: now(),
+ data: {
+ component: {
+ _custom: {
+ type: 'component-definition',
+ display: componentDisplay,
+ },
+ },
+ event,
+ params,
+ },
+ title: event,
+ subtitle: `by ${componentDisplay}`,
+ meta: {
+ componentId,
+ bounds: await appRecord.backend.api.getComponentBounds(instance),
+ },
+ },
+ }, app, ctx)
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+ })
+}
+
+export async function sendTimelineLayers(ctx: BackendContext) {
+ const layers = []
+ for (const layer of ctx.timelineLayers) {
+ try {
+ layers.push({
+ id: layer.id,
+ label: layer.label,
+ color: layer.color,
+ appId: layer.appRecord?.id,
+ pluginId: layer.plugin?.descriptor.id,
+ groupsOnly: layer.groupsOnly,
+ skipScreenshots: layer.skipScreenshots,
+ ignoreNoDurationGroups: layer.ignoreNoDurationGroups,
+ })
+ }
+ catch (e) {
+ if (SharedData.debugInfo) {
+ console.error(e)
+ }
+ }
+ }
+ ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_LAYER_LIST, {
+ layers,
+ })
+}
+
+export async function addTimelineEvent(options: TimelineEventOptions, app: App, ctx: BackendContext) {
+ if (!SharedData.timelineRecording) {
+ return
+ }
+ const appId = app ? getAppRecordId(app) : null
+ const isAllApps = options.all || !app || appId == null
+
+ const id = ctx.nextTimelineEventId++
+
+ const eventData: TimelineEventOptions & WithId = {
+ id,
+ ...options,
+ all: isAllApps,
+ }
+ ctx.timelineEventMap.set(eventData.id, eventData)
+
+ ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_EVENT, {
+ appId: eventData.all ? 'all' : appId,
+ layerId: eventData.layerId,
+ event: mapTimelineEvent(eventData),
+ })
+
+ const layer = ctx.timelineLayers.find(l => (isAllApps || l.appRecord?.options.app === app) && l.id === options.layerId)
+ if (layer) {
+ layer.events.push(eventData)
+ }
+ else if (SharedData.debugInfo) {
+ console.warn(`Timeline layer ${options.layerId} not found`)
+ }
+}
+
+const initialTime = Date.now()
+export const dateThreshold = initialTime - 1_000_000
+export const perfTimeDiff = initialTime - now()
+
+function mapTimelineEvent(eventData: TimelineEventOptions & WithId) {
+ let time = eventData.event.time
+ if (isPerformanceSupported() && time < dateThreshold) {
+ time += perfTimeDiff
+ }
+ return {
+ id: eventData.id,
+ time: Math.round(time * 1000),
+ logType: eventData.event.logType,
+ groupId: eventData.event.groupId,
+ title: eventData.event.title,
+ subtitle: eventData.event.subtitle,
+ }
+}
+
+export async function clearTimeline(ctx: BackendContext) {
+ ctx.timelineEventMap.clear()
+ for (const layer of ctx.timelineLayers) {
+ layer.events = []
+ }
+ for (const backend of ctx.backends) {
+ await backend.api.clearTimeline()
+ }
+}
+
+export async function sendTimelineEventData(id: ID, ctx: BackendContext) {
+ if (!SharedData.timelineRecording) {
+ return
+ }
+ let data = null
+ const eventData = ctx.timelineEventMap.get(id)
+ if (eventData) {
+ data = await ctx.currentAppRecord.backend.api.inspectTimelineEvent(eventData, ctx.currentAppRecord.options.app)
+ data = stringify(data)
+ }
+ else if (SharedData.debugInfo) {
+ console.warn(`Event ${id} not found`, ctx.timelineEventMap.keys())
+ }
+ ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_EVENT_DATA, {
+ eventId: id,
+ data,
+ })
+}
+
+export function removeLayersForApp(app: App, ctx: BackendContext) {
+ const layers = ctx.timelineLayers.filter(l => l.appRecord?.options.app === app)
+ for (const layer of layers) {
+ const index = ctx.timelineLayers.indexOf(layer)
+ if (index !== -1) {
+ ctx.timelineLayers.splice(index, 1)
+ }
+ for (const e of layer.events) {
+ ctx.timelineEventMap.delete(e.id)
+ }
+ }
+}
+
+export function sendTimelineLayerEvents(appId: string, layerId: string, ctx: BackendContext) {
+ if (!SharedData.timelineRecording) {
+ return
+ }
+ const app = ctx.appRecords.find(ar => ar.id === appId)?.options.app
+ if (!app) {
+ return
+ }
+ const layer = ctx.timelineLayers.find(l => l.appRecord?.options.app === app && l.id === layerId)
+ if (!layer) {
+ return
+ }
+ ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_LAYER_LOAD_EVENTS, {
+ appId,
+ layerId,
+ events: layer.events.map(e => mapTimelineEvent(e)),
+ })
+}
diff --git a/vue-devtools/packages/app-backend-core/src/toast.ts b/vue-devtools/packages/app-backend-core/src/toast.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ff281196860228de587bacedeb27877d7b31498b
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/toast.ts
@@ -0,0 +1,3 @@
+export function installToast() {
+ // @TODO
+}
diff --git a/vue-devtools/packages/app-backend-core/src/util/queue.ts b/vue-devtools/packages/app-backend-core/src/util/queue.ts
new file mode 100644
index 0000000000000000000000000000000000000000..99932bbb4e4e439302f546946a73719240b3b1d1
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/util/queue.ts
@@ -0,0 +1,45 @@
+export interface Job {
+ id: string
+ fn: () => Promise
+}
+
+export class JobQueue {
+ jobs: Job[] = []
+ currentJob: Job
+
+ queue(id: string, fn: Job['fn']) {
+ const job: Job = {
+ id,
+ fn,
+ }
+
+ return new Promise((resolve) => {
+ const onDone = () => {
+ this.currentJob = null
+ const nextJob = this.jobs.shift()
+ if (nextJob) {
+ nextJob.fn()
+ }
+ resolve()
+ }
+
+ const run = () => {
+ this.currentJob = job
+ return job.fn().then(onDone).catch((e) => {
+ console.error(`Job ${job.id} failed:`)
+ console.error(e)
+ })
+ }
+
+ if (this.currentJob) {
+ this.jobs.push({
+ id: job.id,
+ fn: () => run(),
+ })
+ }
+ else {
+ run()
+ }
+ })
+ }
+}
diff --git a/vue-devtools/packages/app-backend-core/src/util/subscriptions.ts b/vue-devtools/packages/app-backend-core/src/util/subscriptions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d57bdbce6fc961d232a023451144031961de8e37
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/src/util/subscriptions.ts
@@ -0,0 +1,26 @@
+const activeSubs: Map> = new Map()
+
+function getSubs(type: string) {
+ let subs = activeSubs.get(type)
+ if (!subs) {
+ subs = new Map()
+ activeSubs.set(type, subs)
+ }
+ return subs
+}
+
+export function subscribe(type: string, key: string) {
+ getSubs(type).set(key, true)
+}
+
+export function unsubscribe(type: string, key: string) {
+ const subs = getSubs(type)
+ subs.delete(key)
+}
+
+export function isSubscribed(
+ type: string,
+ key: string,
+) {
+ return getSubs(type).has(key)
+}
diff --git a/vue-devtools/packages/app-backend-core/tsconfig.json b/vue-devtools/packages/app-backend-core/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..becb763b20bbbd4557ba0717c957b4e3d3d6c81b
--- /dev/null
+++ b/vue-devtools/packages/app-backend-core/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "target": "ES2019",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "types": [
+ "node",
+ "webpack-env"
+ ],
+ "strictBindCallApply": true,
+ "strictFunctionTypes": true,
+ "alwaysStrict": true,
+ // Strict
+ "noImplicitAny": false,
+ "noImplicitThis": true,
+ "sourceMap": true,
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "preserveWatchOutput": true
+ },
+ "include": [
+ "src/**/*"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/vue-devtools/packages/app-backend-vue1/package.json b/vue-devtools/packages/app-backend-vue1/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..76cf42fe95f3ac98c45b14527264424d74cdf3e6
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue1/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "@vue-devtools/app-backend-vue1",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./lib/index.js",
+ "types": "./lib/index.d.ts",
+ "scripts": {
+ "build": "rimraf lib && yarn ts",
+ "build:watch": "yarn ts -w",
+ "ts": "tsc -d -outDir lib"
+ },
+ "dependencies": {
+ "@vue-devtools/app-backend-api": "^0.0.0",
+ "@vue-devtools/shared-utils": "^0.0.0"
+ },
+ "devDependencies": {
+ "@types/node": "^20.11.16",
+ "@types/webpack-env": "^1.15.1",
+ "typescript": "^5.3.3"
+ }
+}
diff --git a/vue-devtools/packages/app-backend-vue1/src/index.ts b/vue-devtools/packages/app-backend-vue1/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8798cc0724da1e800abc7bdb4517c43c57bea97c
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue1/src/index.ts
@@ -0,0 +1,9 @@
+import { defineBackend } from '@vue-devtools/app-backend-api'
+
+export const backend = defineBackend({
+ frameworkVersion: 1,
+ features: [],
+ setup(_api) {
+ // @TODO
+ },
+})
diff --git a/vue-devtools/packages/app-backend-vue1/tsconfig.json b/vue-devtools/packages/app-backend-vue1/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..becb763b20bbbd4557ba0717c957b4e3d3d6c81b
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue1/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "target": "ES2019",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "types": [
+ "node",
+ "webpack-env"
+ ],
+ "strictBindCallApply": true,
+ "strictFunctionTypes": true,
+ "alwaysStrict": true,
+ // Strict
+ "noImplicitAny": false,
+ "noImplicitThis": true,
+ "sourceMap": true,
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "preserveWatchOutput": true
+ },
+ "include": [
+ "src/**/*"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/vue-devtools/packages/app-backend-vue2/package.json b/vue-devtools/packages/app-backend-vue2/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..1a95fec7d7cff3cd25b8a3dd724e7eb8dd830176
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue2/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "@vue-devtools/app-backend-vue2",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./lib/index.js",
+ "types": "./lib/index.d.ts",
+ "scripts": {
+ "build": "rimraf lib && yarn ts",
+ "build:watch": "yarn ts -w",
+ "ts": "tsc -d -outDir lib"
+ },
+ "dependencies": {
+ "@vue-devtools/app-backend-api": "^0.0.0",
+ "@vue-devtools/shared-utils": "^0.0.0",
+ "@vue/devtools-api": "^6.0.0-beta.7",
+ "clone-deep": "^4.0.1",
+ "lodash": "^4.17.21"
+ },
+ "devDependencies": {
+ "@types/node": "^20.11.16",
+ "@types/webpack-env": "^1.15.1",
+ "core-js": "^3.20.2",
+ "typescript": "^5.3.3",
+ "vue": "^2.7.10",
+ "vue-loader": "^15.7.1"
+ }
+}
diff --git a/vue-devtools/packages/app-backend-vue2/src/components/data.ts b/vue-devtools/packages/app-backend-vue2/src/components/data.ts
new file mode 100644
index 0000000000000000000000000000000000000000..227e55dd9943410c290882072dbc16f8bd6ff6f9
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue2/src/components/data.ts
@@ -0,0 +1,522 @@
+import type { StateEditor } from '@vue-devtools/shared-utils'
+import { SharedData, camelize, getComponentName, getCustomRefDetails } from '@vue-devtools/shared-utils'
+import type { ComponentState, CustomState, HookPayloads, Hooks, InspectedComponentData } from '@vue/devtools-api'
+import { getFunctionalVnodeMap, getInstanceMap } from './tree'
+import 'core-js/modules/es.object.entries'
+
+/**
+ * Get the detailed information of an inspected instance.
+ */
+export function getInstanceDetails(instance): InspectedComponentData {
+ if (instance.__VUE_DEVTOOLS_FUNCTIONAL_LEGACY__) {
+ const vnode = findInstanceOrVnode(instance.__VUE_DEVTOOLS_UID__)
+
+ if (!vnode) {
+ return null
+ }
+
+ const fakeInstance = {
+ $options: vnode.fnOptions,
+ ...(vnode.devtoolsMeta?.renderContext.props),
+ }
+
+ if (!fakeInstance.$options.props && vnode.devtoolsMeta?.renderContext.props) {
+ fakeInstance.$options.props = Object.keys(vnode.devtoolsMeta.renderContext.props).reduce((obj, key) => {
+ obj[key] = {}
+ return obj
+ }, {})
+ }
+
+ const data = {
+ id: instance.__VUE_DEVTOOLS_UID__,
+ name: getComponentName(vnode.fnOptions),
+ file: instance.type ? instance.type.__file : vnode.fnOptions.__file || null,
+ state: getFunctionalInstanceState(fakeInstance),
+ functional: true,
+ }
+
+ return data
+ }
+
+ const data: InspectedComponentData = {
+ id: instance.__VUE_DEVTOOLS_UID__,
+ name: getInstanceName(instance),
+ state: getInstanceState(instance),
+ file: null,
+ }
+
+ if (instance.$vnode?.componentOptions?.Ctor?.options) {
+ data.file = instance.$vnode.componentOptions.Ctor.options.__file || null
+ }
+
+ return data
+}
+
+function getInstanceState(instance): ComponentState[] {
+ return processProps(instance).concat(
+ processState(instance),
+ processSetupState(instance),
+ processRefs(instance),
+ processComputed(instance),
+ processInjected(instance),
+ processRouteContext(instance),
+ processVuexGetters(instance),
+ processFirebaseBindings(instance),
+ processObservables(instance),
+ processAttrs(instance),
+ )
+}
+
+function getFunctionalInstanceState(instance): ComponentState[] {
+ return processProps(instance)
+}
+
+export function getCustomInstanceDetails(instance) {
+ const state = getInstanceState(instance)
+ return {
+ _custom: {
+ type: 'component',
+ id: instance.__VUE_DEVTOOLS_UID__,
+ display: getInstanceName(instance),
+ tooltip: 'Component instance',
+ value: reduceStateList(state),
+ fields: {
+ abstract: true,
+ },
+ },
+ }
+}
+
+export function reduceStateList(list) {
+ if (!list.length) {
+ return undefined
+ }
+ return list.reduce((map, item) => {
+ const key = item.type || 'data'
+ const obj = map[key] = map[key] || {}
+ obj[item.key] = item.value
+ return map
+ }, {})
+}
+
+/**
+ * Get the appropriate display name for an instance.
+ */
+export function getInstanceName(instance): string {
+ const name = getComponentName(instance.$options || instance.fnOptions || {})
+ if (name) {
+ return name
+ }
+ return instance.$root === instance
+ ? 'Root'
+ : 'Anonymous Component'
+}
+
+/**
+ * Process the props of an instance.
+ * Make sure return a plain object because window.postMessage()
+ * will throw an Error if the passed object contains Functions.
+ */
+function processProps(instance): ComponentState[] {
+ const props = instance.$options.props
+ const propsData = []
+ for (let key in props) {
+ const prop = props[key]
+ key = camelize(key)
+ propsData.push({
+ type: 'props',
+ key,
+ value: instance[key],
+ meta: prop
+ ? {
+ type: prop.type ? getPropType(prop.type) : 'any',
+ required: !!prop.required,
+ }
+ : {
+ type: 'invalid',
+ },
+ editable: SharedData.editableProps,
+ })
+ }
+ return propsData
+}
+
+function processAttrs(instance): ComponentState[] {
+ return Object.entries(instance.$attrs || {}).map(([key, value]) => {
+ return {
+ type: '$attrs',
+ key,
+ value,
+ }
+ })
+}
+
+const fnTypeRE = /^(?:function|class) (\w+)/
+
+/**
+ * Convert prop type constructor to string.
+ */
+function getPropType(type) {
+ if (Array.isArray(type)) {
+ return type.map(t => getPropType(t)).join(' or ')
+ }
+ if (type == null) {
+ return 'null'
+ }
+ const match = type.toString().match(fnTypeRE)
+ return typeof type === 'function'
+ ? (match && match[1]) || 'any'
+ : 'any'
+}
+
+/**
+ * Process state, filtering out props and "clean" the result
+ * with a JSON dance. This removes functions which can cause
+ * errors during structured clone used by window.postMessage.
+ */
+function processState(instance): ComponentState[] {
+ const props = instance.$options.props
+ const getters
+ = instance.$options.vuex
+ && instance.$options.vuex.getters
+ return Object.keys(instance._data)
+ .filter(key => (
+ !(props && key in props)
+ && !(getters && key in getters)
+ ))
+ .map(key => ({
+ key,
+ type: 'data',
+ value: instance._data[key],
+ editable: true,
+ }))
+}
+
+function processSetupState(instance) {
+ const state = instance._setupProxy || instance
+ const raw = instance._setupState
+ if (!raw) {
+ return []
+ }
+
+ return Object.keys(raw)
+ .filter(key => !key.startsWith('__'))
+ .map((key) => {
+ const value = returnError(() => toRaw(state[key]))
+
+ const rawData = raw[key]
+
+ let result: any
+
+ if (rawData) {
+ const info = getSetupStateInfo(rawData)
+
+ const objectType = info.computed ? 'Computed' : info.ref ? 'Ref' : info.reactive ? 'Reactive' : null
+ const isState = info.ref || info.computed || info.reactive
+ const isOther = typeof value === 'function' || typeof value?.render === 'function'
+ // effect is a Vue 2 Watcher instance
+ const raw = rawData.effect?.expression || rawData.effect?.getter?.toString()
+
+ result = {
+ ...objectType ? { objectType } : {},
+ ...raw ? { raw } : {},
+ editable: isState && !info.readonly,
+ type: isOther ? 'setup (other)' : 'setup',
+ }
+ }
+ else {
+ result = {
+ type: 'setup',
+ }
+ }
+
+ return {
+ key,
+ value,
+ ...result,
+ }
+ })
+}
+
+function returnError(cb: () => any) {
+ try {
+ return cb()
+ }
+ catch (e) {
+ return e
+ }
+}
+
+function isRef(raw: any): boolean {
+ return !!raw.__v_isRef
+}
+
+function isComputed(raw: any): boolean {
+ return isRef(raw) && !!raw.effect
+}
+
+function isReactive(raw: any): boolean {
+ return !!raw.__ob__
+}
+
+function isReadOnly(raw: any): boolean {
+ return !!raw.__v_isReadonly
+}
+
+function toRaw(value: any) {
+ if (value?.__v_raw) {
+ return value.__v_raw
+ }
+ return value
+}
+
+function getSetupStateInfo(raw: any) {
+ return {
+ ref: isRef(raw),
+ computed: isComputed(raw),
+ reactive: isReactive(raw),
+ readonly: isReadOnly(raw),
+ }
+}
+
+export function getCustomObjectDetails(object: any, _proto: string): CustomState | undefined {
+ const info = getSetupStateInfo(object)
+
+ const isState = info.ref || info.computed || info.reactive
+ if (isState) {
+ const objectType = info.computed ? 'Computed' : info.ref ? 'Ref' : info.reactive ? 'Reactive' : null
+ const value = toRaw(info.reactive ? object : object._value)
+ const raw = object.effect?.raw?.toString() || object.effect?.fn?.toString()
+ return {
+ _custom: {
+ type: objectType.toLowerCase(),
+ objectType,
+ value,
+ ...raw ? { tooltip: `${raw}` } : {},
+ },
+ }
+ }
+}
+
+/**
+ * Process refs
+ */
+function processRefs(instance): ComponentState[] {
+ return Object.keys(instance.$refs)
+ .filter(key => instance.$refs[key])
+ .map(key => getCustomRefDetails(instance, key, instance.$refs[key]))
+}
+
+/**
+ * Process the computed properties of an instance.
+ */
+function processComputed(instance): ComponentState[] {
+ const computed = []
+ const defs = instance.$options.computed || {}
+ // use for...in here because if 'computed' is not defined
+ // on component, computed properties will be placed in prototype
+ // and Object.keys does not include
+ // properties from object's prototype
+ for (const key in defs) {
+ const def = defs[key]
+ const type = typeof def === 'function' && def.vuex
+ ? 'vuex bindings'
+ : 'computed'
+ // use try ... catch here because some computed properties may
+ // throw error during its evaluation
+ let computedProp = null
+ try {
+ computedProp = {
+ type,
+ key,
+ value: instance[key],
+ }
+ }
+ catch (e) {
+ computedProp = {
+ type,
+ key,
+ value: e,
+ }
+ }
+
+ computed.push(computedProp)
+ }
+
+ return computed
+}
+
+/**
+ * Process Vuex getters.
+ */
+function processInjected(instance): ComponentState[] {
+ const injected = instance.$options.inject
+
+ if (injected) {
+ return Object.keys(injected).map((key) => {
+ return {
+ key,
+ type: 'injected',
+ value: instance[key],
+ }
+ })
+ }
+ else {
+ return []
+ }
+}
+
+/**
+ * Process possible vue-router $route context
+ */
+function processRouteContext(instance): ComponentState[] {
+ try {
+ const route = instance.$route
+ if (route) {
+ const { path, query, params } = route
+ const value: any = { path, query, params }
+ if (route.fullPath) {
+ value.fullPath = route.fullPath
+ }
+ if (route.hash) {
+ value.hash = route.hash
+ }
+ if (route.name) {
+ value.name = route.name
+ }
+ if (route.meta) {
+ value.meta = route.meta
+ }
+ return [{
+ key: '$route',
+ type: 'route',
+ value: {
+ _custom: {
+ type: 'router',
+ abstract: true,
+ value,
+ },
+ },
+ }]
+ }
+ }
+ catch (e) {
+ // Invalid $router
+ }
+ return []
+}
+
+/**
+ * Process Vuex getters.
+ */
+function processVuexGetters(instance): ComponentState[] {
+ const getters
+ = instance.$options.vuex
+ && instance.$options.vuex.getters
+ if (getters) {
+ return Object.keys(getters).map((key) => {
+ return {
+ type: 'vuex getters',
+ key,
+ value: instance[key],
+ }
+ })
+ }
+ else {
+ return []
+ }
+}
+
+/**
+ * Process Firebase bindings.
+ */
+function processFirebaseBindings(instance): ComponentState[] {
+ const refs = instance.$firebaseRefs
+ if (refs) {
+ return Object.keys(refs).map((key) => {
+ return {
+ type: 'firebase bindings',
+ key,
+ value: instance[key],
+ }
+ })
+ }
+ else {
+ return []
+ }
+}
+
+/**
+ * Process vue-rx observable bindings.
+ */
+function processObservables(instance): ComponentState[] {
+ const obs = instance.$observables
+ if (obs) {
+ return Object.keys(obs).map((key) => {
+ return {
+ type: 'observables',
+ key,
+ value: instance[key],
+ }
+ })
+ }
+ else {
+ return []
+ }
+}
+
+export function findInstanceOrVnode(id) {
+ if (/:functional:/.test(id)) {
+ const [refId] = id.split(':functional:')
+ const map = getFunctionalVnodeMap()?.get(refId)
+ return map && map[id]
+ }
+ return getInstanceMap()?.get(id)
+}
+
+export function editState(
+ {
+ componentInstance,
+ path,
+ state,
+ type,
+ }: HookPayloads[Hooks.EDIT_COMPONENT_STATE],
+ stateEditor: StateEditor,
+) {
+ if (!['data', 'props', 'computed', 'setup'].includes(type)) {
+ return
+ }
+
+ let target: any
+ const targetPath: string[] = path.slice()
+
+ if (stateEditor.has(componentInstance._props, path, !!state.newKey)) {
+ // props
+ target = componentInstance._props
+ }
+ else if (
+ componentInstance._setupState
+ && Object.keys(componentInstance._setupState).includes(path[0])
+ ) {
+ // setup
+ target = componentInstance._setupProxy
+
+ const currentValue = stateEditor.get(target, path)
+ if (currentValue != null) {
+ const info = getSetupStateInfo(currentValue)
+ if (info.readonly) {
+ return
+ }
+ }
+ }
+ else {
+ target = componentInstance._data
+ }
+
+ stateEditor.set(
+ target,
+ targetPath,
+ 'value' in state ? state.value : undefined,
+ stateEditor.createDefaultSetCallback(state),
+ )
+}
diff --git a/vue-devtools/packages/app-backend-vue2/src/components/el.ts b/vue-devtools/packages/app-backend-vue2/src/components/el.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bfd084ae60ef60ad9ab015123eb3fe29c9cb9403
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue2/src/components/el.ts
@@ -0,0 +1,136 @@
+import { inDoc, isBrowser, target } from '@vue-devtools/shared-utils'
+
+function createRect() {
+ const rect = {
+ top: 0,
+ bottom: 0,
+ left: 0,
+ right: 0,
+ get width() { return rect.right - rect.left },
+ get height() { return rect.bottom - rect.top },
+ }
+ return rect
+}
+
+function mergeRects(a, b) {
+ if (!a.top || b.top < a.top) {
+ a.top = b.top
+ }
+ if (!a.bottom || b.bottom > a.bottom) {
+ a.bottom = b.bottom
+ }
+ if (!a.left || b.left < a.left) {
+ a.left = b.left
+ }
+ if (!a.right || b.right > a.right) {
+ a.right = b.right
+ }
+ return a
+}
+
+/**
+ * Get the client rect for an instance.
+ */
+export function getInstanceOrVnodeRect(instance) {
+ const el = instance.$el || instance.elm
+
+ if (!isBrowser) {
+ // TODO: Find position from instance or a vnode (for functional components).
+
+ return
+ }
+ if (!inDoc(el)) {
+ return
+ }
+
+ if (instance._isFragment) {
+ return addIframePosition(getLegacyFragmentRect(instance), getElWindow(instance.$root.$el))
+ }
+ else if (el.nodeType === 1) {
+ return addIframePosition(el.getBoundingClientRect(), getElWindow(el))
+ }
+}
+
+/**
+ * Highlight a fragment instance.
+ * Loop over its node range and determine its bounding box.
+ */
+function getLegacyFragmentRect({ _fragmentStart, _fragmentEnd }) {
+ const rect = createRect()
+ util().mapNodeRange(_fragmentStart, _fragmentEnd, (node) => {
+ let childRect
+ if (node.nodeType === 1 || node.getBoundingClientRect) {
+ childRect = node.getBoundingClientRect()
+ }
+ else if (node.nodeType === 3 && node.data.trim()) {
+ childRect = getTextRect(node)
+ }
+ if (childRect) {
+ mergeRects(rect, childRect)
+ }
+ })
+ return rect
+}
+
+let range: Range
+/**
+ * Get the bounding rect for a text node using a Range.
+ */
+function getTextRect(node: Text) {
+ if (!isBrowser) {
+ return
+ }
+ if (!range) {
+ range = document.createRange()
+ }
+
+ range.selectNode(node)
+
+ return range.getBoundingClientRect()
+}
+
+/**
+ * Get Vue's util
+ */
+function util() {
+ return target.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue.util
+}
+
+export function findRelatedComponent(el) {
+ while (!el.__vue__ && el.parentElement) {
+ el = el.parentElement
+ }
+ return el.__vue__
+}
+
+function getElWindow(el: HTMLElement) {
+ return el.ownerDocument.defaultView
+}
+
+function addIframePosition(bounds, win: any) {
+ if (win.__VUE_DEVTOOLS_IFRAME__) {
+ const rect = mergeRects(createRect(), bounds)
+ const iframeBounds = win.__VUE_DEVTOOLS_IFRAME__.getBoundingClientRect()
+ rect.top += iframeBounds.top
+ rect.bottom += iframeBounds.top
+ rect.left += iframeBounds.left
+ rect.right += iframeBounds.left
+ if (win.parent) {
+ return addIframePosition(rect, win.parent)
+ }
+ return rect
+ }
+ return bounds
+}
+
+export function getRootElementsFromComponentInstance(instance) {
+ if (instance._isFragment) {
+ const list = []
+ const { _fragmentStart, _fragmentEnd } = instance
+ util().mapNodeRange(_fragmentStart, _fragmentEnd, (node) => {
+ list.push(node)
+ })
+ return list
+ }
+ return [instance.$el]
+}
diff --git a/vue-devtools/packages/app-backend-vue2/src/components/perf.ts b/vue-devtools/packages/app-backend-vue2/src/components/perf.ts
new file mode 100644
index 0000000000000000000000000000000000000000..517cc1944303d938d61b80d23515f28039c2b379
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue2/src/components/perf.ts
@@ -0,0 +1,59 @@
+import type { DevtoolsApi } from '@vue-devtools/app-backend-api'
+import { HookEvents, SharedData } from '@vue-devtools/shared-utils'
+import { getInstanceMap } from './tree'
+
+const COMPONENT_HOOKS = {
+ beforeCreate: { start: 'create' },
+ created: { end: 'create' },
+ beforeMount: { start: 'mount' },
+ mounted: { end: 'mount' },
+ beforeUpdate: { start: 'update' },
+ updated: { end: 'update' },
+ beforeDestroyed: { start: 'destroy' },
+ destroyed: { end: 'destroy' },
+}
+
+export function initPerf(api: DevtoolsApi, app, Vue) {
+ // Global mixin
+ Vue.mixin({
+ beforeCreate() {
+ applyPerfHooks(api, this, app)
+ },
+ })
+
+ // Apply to existing components
+ getInstanceMap()?.forEach(vm => applyPerfHooks(api, vm, app))
+}
+
+export function applyPerfHooks(api: DevtoolsApi, vm, app) {
+ if (vm.$options.$_devtoolsPerfHooks) {
+ return
+ }
+ vm.$options.$_devtoolsPerfHooks = true
+
+ for (const hook in COMPONENT_HOOKS) {
+ const { start, end } = COMPONENT_HOOKS[hook]
+ const handler = function (this: any) {
+ if (SharedData.performanceMonitoringEnabled) {
+ api.ctx.hook.emit(
+ start ? HookEvents.PERFORMANCE_START : HookEvents.PERFORMANCE_END,
+ app,
+ this._uid,
+ this,
+ start ?? end,
+ api.now(),
+ )
+ }
+ }
+ const currentValue = vm.$options[hook]
+ if (Array.isArray(currentValue)) {
+ vm.$options[hook] = [handler, ...currentValue]
+ }
+ else if (typeof currentValue === 'function') {
+ vm.$options[hook] = [handler, currentValue]
+ }
+ else {
+ vm.$options[hook] = [handler]
+ }
+ }
+}
diff --git a/vue-devtools/packages/app-backend-vue2/src/components/tree.ts b/vue-devtools/packages/app-backend-vue2/src/components/tree.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e73efa30af7a5976cacdb13d9a45460260124195
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue2/src/components/tree.ts
@@ -0,0 +1,378 @@
+import type { AppRecord, BackendContext, DevtoolsApi } from '@vue-devtools/app-backend-api'
+import { classify, kebabize } from '@vue-devtools/shared-utils'
+import type { ComponentInstance, ComponentTreeNode } from '@vue/devtools-api'
+import { getRootElementsFromComponentInstance } from './el'
+import { applyPerfHooks } from './perf.js'
+import { applyTrackingUpdateHook } from './update-tracking.js'
+import { getInstanceName, getRenderKey, getUniqueId, isBeingDestroyed } from './util'
+
+let instanceMap: Map = new Map()
+let functionalVnodeMap: Map = new Map()
+
+export function getInstanceMap() {
+ return instanceMap
+}
+
+export function getFunctionalVnodeMap() {
+ return functionalVnodeMap
+}
+
+let appRecord: AppRecord
+let api: DevtoolsApi
+
+const consoleBoundInstances = Array(5)
+
+let filter = ''
+let recursively = false
+const functionalIds = new Map()
+
+// Dedupe instances
+// Some instances may be both on a component and on a child abstract/functional component
+const captureIds = new Map()
+
+export async function walkTree(instance, pFilter: string, pRecursively: boolean, api: DevtoolsApi, ctx: BackendContext): Promise {
+ initCtx(api, ctx)
+ filter = pFilter
+ recursively = pRecursively
+ functionalIds.clear()
+ captureIds.clear()
+ const result: ComponentTreeNode[] = flatten(await findQualifiedChildren(instance))
+ return result
+}
+
+export function getComponentParents(instance, api: DevtoolsApi, ctx: BackendContext) {
+ initCtx(api, ctx)
+ const captureIds = new Map()
+
+ const captureId = (vm) => {
+ const id = vm.__VUE_DEVTOOLS_UID__ = getUniqueId(vm)
+ if (captureIds.has(id)) {
+ return
+ }
+ captureIds.set(id, undefined)
+ if (vm.__VUE_DEVTOOLS_FUNCTIONAL_LEGACY__) {
+ markFunctional(id, vm.vnode)
+ }
+ else {
+ mark(vm)
+ }
+ }
+
+ const parents = []
+ captureId(instance)
+ let parent = instance
+ // eslint-disable-next-line no-cond-assign
+ while ((parent = parent.$parent)) {
+ captureId(parent)
+ parents.push(parent)
+ }
+ return parents
+}
+
+function initCtx(_api: DevtoolsApi, ctx: BackendContext) {
+ appRecord = ctx.currentAppRecord
+ api = _api
+ if (!appRecord.meta) {
+ appRecord.meta = {}
+ }
+ if (!appRecord.meta.instanceMap) {
+ appRecord.meta.instanceMap = new Map()
+ }
+ instanceMap = appRecord.meta.instanceMap
+ if (!appRecord.meta.functionalVnodeMap) {
+ appRecord.meta.functionalVnodeMap = new Map()
+ }
+ functionalVnodeMap = appRecord.meta.functionalVnodeMap
+}
+
+/**
+ * Iterate through an array of instances and flatten it into
+ * an array of qualified instances. This is a depth-first
+ * traversal - e.g. if an instance is not matched, we will
+ * recursively go deeper until a qualified child is found.
+ */
+function findQualifiedChildrenFromList(instances: any[]): Promise {
+ instances = instances
+ .filter(child => !isBeingDestroyed(child))
+ return Promise.all(!filter
+ ? instances.map(capture)
+ : Array.prototype.concat.apply([], instances.map(findQualifiedChildren)))
+}
+
+/**
+ * Find qualified children from a single instance.
+ * If the instance itself is qualified, just return itself.
+ * This is ok because [].concat works in both cases.
+ */
+async function findQualifiedChildren(instance): Promise {
+ if (isQualified(instance)) {
+ return [await capture(instance)]
+ }
+ else {
+ let children = await findQualifiedChildrenFromList(instance.$children)
+
+ // Find functional components in recursively in non-functional vnodes.
+ if (instance._vnode && instance._vnode.children) {
+ const list = await Promise.all(flatten>((instance._vnode.children as any[]).filter(child => !child.componentInstance).map(captureChild)))
+ // Filter qualified children.
+ const additionalChildren = list.filter(instance => isQualified(instance))
+ children = children.concat(additionalChildren)
+ }
+
+ return children
+ }
+}
+
+/**
+ * Get children from a component instance.
+ */
+function getInternalInstanceChildren(instance): any[] {
+ if (instance.$children) {
+ return instance.$children
+ }
+ return []
+}
+
+/**
+ * Check if an instance is qualified.
+ */
+function isQualified(instance): boolean {
+ const name = getInstanceName(instance)
+ return classify(name).toLowerCase().includes(filter)
+ || kebabize(name).toLowerCase().includes(filter)
+}
+
+function flatten(items: any[]): T[] {
+ const r = items.reduce((acc, item) => {
+ if (Array.isArray(item)) {
+ let children = []
+ for (const i of item) {
+ if (Array.isArray(i)) {
+ children = children.concat(flatten(i))
+ }
+ else {
+ children.push(i)
+ }
+ }
+ acc.push(...children)
+ }
+ else if (item) {
+ acc.push(item)
+ }
+
+ return acc
+ }, [] as T[])
+ return r
+}
+
+function captureChild(child): Promise {
+ if (child.fnContext && !child.componentInstance) {
+ return capture(child)
+ }
+ else if (child.componentInstance) {
+ if (!isBeingDestroyed(child.componentInstance)) {
+ return capture(child.componentInstance)
+ }
+ }
+ else if (child.children) {
+ return Promise.all(flatten>(child.children.map(captureChild)))
+ }
+}
+
+/**
+ * Capture the meta information of an instance. (recursive)
+ */
+async function capture(instance, _index?: number, _list?: any[]): Promise {
+ if (instance.__VUE_DEVTOOLS_FUNCTIONAL_LEGACY__) {
+ instance = instance.vnode
+ }
+
+ if (instance.$options && instance.$options.abstract && instance._vnode && instance._vnode.componentInstance) {
+ instance = instance._vnode.componentInstance
+ }
+
+ if (instance.$options?.devtools?.hide) {
+ return
+ }
+
+ // Functional component.
+ if (instance.fnContext && !instance.componentInstance) {
+ const contextUid = instance.fnContext.__VUE_DEVTOOLS_UID__
+ let id = functionalIds.get(contextUid)
+ if (id == null) {
+ id = 0
+ }
+ else {
+ id++
+ }
+ functionalIds.set(contextUid, id)
+ const functionalId = `${contextUid}:functional:${id}`
+ markFunctional(functionalId, instance)
+
+ const childrenPromise = (instance.children
+ ? instance.children.map(
+ child => child.fnContext
+ ? captureChild(child)
+ : child.componentInstance
+ ? capture(child.componentInstance)
+ : undefined,
+ )
+ // router-view has both fnContext and componentInstance on vnode.
+ : instance.componentInstance ? [capture(instance.componentInstance)] : [])
+
+ // await all childrenCapture to-be resolved
+ const children = (await Promise.all(childrenPromise)).filter(Boolean) as ComponentTreeNode[]
+
+ const treeNode = {
+ uid: functionalId,
+ id: functionalId,
+ tags: [
+ {
+ label: 'functional',
+ textColor: 0x555555,
+ backgroundColor: 0xEEEEEE,
+ },
+ ],
+ name: getInstanceName(instance),
+ renderKey: getRenderKey(instance.key),
+ children,
+ hasChildren: !!children.length,
+ inactive: false,
+ isFragment: false, // TODO: Check what is it for.
+ autoOpen: recursively,
+ }
+ return api.visitComponentTree(
+ instance,
+ treeNode,
+ filter,
+ appRecord?.options?.app,
+ )
+ }
+ // instance._uid is not reliable in devtools as there
+ // may be 2 roots with same _uid which causes unexpected
+ // behaviour
+ instance.__VUE_DEVTOOLS_UID__ = getUniqueId(instance, appRecord)
+
+ // Dedupe
+ if (captureIds.has(instance.__VUE_DEVTOOLS_UID__)) {
+ return
+ }
+ else {
+ captureIds.set(instance.__VUE_DEVTOOLS_UID__, undefined)
+ }
+
+ mark(instance)
+ const name = getInstanceName(instance)
+
+ const children = (await Promise.all((await getInternalInstanceChildren(instance))
+ .filter(child => !isBeingDestroyed(child))
+ .map(capture))).filter(Boolean)
+
+ const ret: ComponentTreeNode = {
+ uid: instance._uid,
+ id: instance.__VUE_DEVTOOLS_UID__,
+ name,
+ renderKey: getRenderKey(instance.$vnode ? instance.$vnode.key : null),
+ inactive: !!instance._inactive,
+ isFragment: !!instance._isFragment,
+ children,
+ hasChildren: !!children.length,
+ autoOpen: recursively,
+ tags: [],
+ meta: {},
+ }
+
+ if (instance._vnode && instance._vnode.children) {
+ const vnodeChildren = await Promise.all(flatten(instance._vnode.children.map(captureChild)))
+ ret.children = ret.children.concat(
+ flatten(vnodeChildren).filter(Boolean),
+ )
+ ret.hasChildren = !!ret.children.length
+ }
+
+ // ensure correct ordering
+ const rootElements = getRootElementsFromComponentInstance(instance)
+ const firstElement = rootElements[0]
+ if (firstElement?.parentElement) {
+ const parentInstance = instance.$parent
+ const parentRootElements = parentInstance ? getRootElementsFromComponentInstance(parentInstance) : []
+ let el = firstElement
+ const indexList = []
+ do {
+ indexList.push(Array.from(el.parentElement.childNodes).indexOf(el))
+ el = el.parentElement
+ } while (el.parentElement && parentRootElements.length && !parentRootElements.includes(el))
+ ret.domOrder = indexList.reverse()
+ }
+ else {
+ ret.domOrder = [-1]
+ }
+
+ // check if instance is available in console
+ const consoleId = consoleBoundInstances.indexOf(instance.__VUE_DEVTOOLS_UID__)
+ ret.consoleId = consoleId > -1 ? `$vm${consoleId}` : null
+
+ // check router view
+ const isRouterView2 = instance.$vnode?.data?.routerView
+ if (instance._routerView || isRouterView2) {
+ ret.isRouterView = true
+ if (!instance._inactive && instance.$route) {
+ const matched = instance.$route.matched
+ const depth = isRouterView2
+ ? instance.$vnode.data.routerViewDepth
+ : instance._routerView.depth
+ ret.meta.matchedRouteSegment
+ = matched
+ && matched[depth]
+ && (isRouterView2 ? matched[depth].path : matched[depth].handler.path)
+ }
+ ret.tags.push({
+ label: `router-view${ret.meta.matchedRouteSegment ? `: ${ret.meta.matchedRouteSegment}` : ''}`,
+ textColor: 0x000000,
+ backgroundColor: 0xFF8344,
+ })
+ }
+ return api.visitComponentTree(
+ instance,
+ ret,
+ filter,
+ appRecord?.options?.app,
+ )
+}
+
+/**
+ * Mark an instance as captured and store it in the instance map.
+ *
+ * @param {Vue} instance
+ */
+
+function mark(instance) {
+ const refId = instance.__VUE_DEVTOOLS_UID__
+ if (!instanceMap.has(refId)) {
+ instanceMap.set(refId, instance)
+ appRecord.instanceMap.set(refId, instance)
+ instance.$on('hook:beforeDestroy', () => {
+ instanceMap.delete(refId)
+ })
+ applyPerfHooks(api, instance, appRecord.options.app)
+ applyTrackingUpdateHook(api, instance)
+ }
+}
+
+function markFunctional(id, vnode) {
+ const refId = vnode.fnContext.__VUE_DEVTOOLS_UID__
+ if (!functionalVnodeMap.has(refId)) {
+ functionalVnodeMap.set(refId, {})
+ vnode.fnContext.$on('hook:beforeDestroy', () => {
+ functionalVnodeMap.delete(refId)
+ })
+ }
+
+ functionalVnodeMap.get(refId)[id] = vnode
+
+ appRecord.instanceMap.set(id, {
+ __VUE_DEVTOOLS_UID__: id,
+ __VUE_DEVTOOLS_FUNCTIONAL_LEGACY__: true,
+ vnode,
+ } as unknown as ComponentInstance)
+}
diff --git a/vue-devtools/packages/app-backend-vue2/src/components/update-tracking.ts b/vue-devtools/packages/app-backend-vue2/src/components/update-tracking.ts
new file mode 100644
index 0000000000000000000000000000000000000000..98264ca9795dcd5e58572eb50b6f5851978962a3
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue2/src/components/update-tracking.ts
@@ -0,0 +1,52 @@
+import type { DevtoolsApi } from '@vue-devtools/app-backend-api'
+import { HookEvents, SharedData } from '@vue-devtools/shared-utils'
+import throttle from 'lodash/throttle'
+import { getUniqueId } from './util.js'
+
+export function initUpdateTracking(api: DevtoolsApi, Vue) {
+ // Global mixin
+ Vue.mixin({
+ beforeCreate() {
+ applyTrackingUpdateHook(api, this)
+ },
+ })
+}
+
+const COMPONENT_HOOKS = [
+ 'created',
+ 'updated',
+]
+
+export function applyTrackingUpdateHook(api: DevtoolsApi, vm) {
+ if (vm.$options.$_devtoolsUpdateTrackingHooks) {
+ return
+ }
+ vm.$options.$_devtoolsUpdateTrackingHooks = true
+
+ const handler = throttle(async function (this: any) {
+ if (SharedData.trackUpdates) {
+ api.ctx.hook.emit(HookEvents.TRACK_UPDATE, getUniqueId(this), api.ctx)
+
+ const parents = await api.walkComponentParents(this)
+ for (const parent of parents) {
+ api.ctx.hook.emit(HookEvents.TRACK_UPDATE, getUniqueId(parent), api.ctx)
+ }
+ }
+
+ if (SharedData.flashUpdates) {
+ api.ctx.hook.emit(HookEvents.FLASH_UPDATE, this, api.backend)
+ }
+ }, 100)
+ for (const hook of COMPONENT_HOOKS) {
+ const currentValue = vm.$options[hook]
+ if (Array.isArray(currentValue)) {
+ vm.$options[hook] = [handler, ...currentValue]
+ }
+ else if (typeof currentValue === 'function') {
+ vm.$options[hook] = [handler, currentValue]
+ }
+ else {
+ vm.$options[hook] = [handler]
+ }
+ }
+}
diff --git a/vue-devtools/packages/app-backend-vue2/src/components/util.ts b/vue-devtools/packages/app-backend-vue2/src/components/util.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5d3cd6e9cf9a16ef4c92c83fec80481d0baa2582
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue2/src/components/util.ts
@@ -0,0 +1,55 @@
+import { getComponentName } from '@vue-devtools/shared-utils'
+import type { AppRecord } from '@vue-devtools/app-backend-api'
+
+export function isBeingDestroyed(instance) {
+ return instance._isBeingDestroyed
+}
+
+/**
+ * Get the appropriate display name for an instance.
+ */
+export function getInstanceName(instance) {
+ const name = getComponentName(instance.$options || instance.fnOptions || {})
+ if (name) {
+ return name
+ }
+ return instance.$root === instance
+ ? 'Root'
+ : 'Anonymous Component'
+}
+
+export function getRenderKey(value): string {
+ if (value == null) {
+ return
+ }
+ const type = typeof value
+ if (type === 'number') {
+ return value.toString()
+ }
+ else if (type === 'string') {
+ return `'${value}'`
+ }
+ else if (Array.isArray(value)) {
+ return 'Array'
+ }
+ else {
+ return 'Object'
+ }
+}
+
+/**
+ * Returns a devtools unique id for instance.
+ */
+export function getUniqueId(instance, appRecord?: AppRecord): string {
+ if (instance.__VUE_DEVTOOLS_UID__ != null) {
+ return instance.__VUE_DEVTOOLS_UID__
+ }
+ let rootVueId = instance.$root.__VUE_DEVTOOLS_APP_RECORD_ID__
+ if (!rootVueId && appRecord) {
+ rootVueId = appRecord.id
+ }
+ if (!rootVueId) {
+ rootVueId = '_unmounted'
+ }
+ return `${rootVueId}:${instance._uid}`
+}
diff --git a/vue-devtools/packages/app-backend-vue2/src/events.ts b/vue-devtools/packages/app-backend-vue2/src/events.ts
new file mode 100644
index 0000000000000000000000000000000000000000..41d1c7d57409d0de11e8edbd76617540be52c1c3
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue2/src/events.ts
@@ -0,0 +1,32 @@
+import type { BackendContext } from '@vue-devtools/app-backend-api'
+import { HookEvents } from '@vue-devtools/shared-utils'
+
+const internalRE = /^(?:pre-)?hook:/
+
+function wrap(app, Vue, method, ctx: BackendContext) {
+ const original = Vue.prototype[method]
+ if (original) {
+ Vue.prototype[method] = function (...args) {
+ const res = original.apply(this, args)
+ logEvent(this, method, args[0], args.slice(1))
+ return res
+ }
+ }
+
+ function logEvent(vm, type, eventName, payload) {
+ // The string check is important for compat with 1.x where the first
+ // argument may be an object instead of a string.
+ // this also ensures the event is only logged for direct $emit (source)
+ // instead of by $dispatch/$broadcast
+ if (typeof eventName === 'string' && !internalRE.test(eventName)) {
+ const instance = vm._self || vm
+ ctx.hook.emit(HookEvents.COMPONENT_EMIT, app, instance, eventName, payload)
+ }
+ }
+}
+
+export function wrapVueForEvents(app, Vue, ctx: BackendContext) {
+ ['$emit', '$broadcast', '$dispatch'].forEach((method) => {
+ wrap(app, Vue, method, ctx)
+ })
+}
diff --git a/vue-devtools/packages/app-backend-vue2/src/index.ts b/vue-devtools/packages/app-backend-vue2/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..32aba118e10ab70ee055ac2bbe2783c346646ba6
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue2/src/index.ts
@@ -0,0 +1,115 @@
+import { BuiltinBackendFeature, defineBackend } from '@vue-devtools/app-backend-api'
+import { backendInjections, getComponentName } from '@vue-devtools/shared-utils'
+import type { ComponentInstance } from '@vue/devtools-api'
+import { editState, getCustomInstanceDetails, getInstanceDetails } from './components/data'
+import { findRelatedComponent, getInstanceOrVnodeRect, getRootElementsFromComponentInstance } from './components/el'
+import { initPerf } from './components/perf.js'
+import { getComponentParents, getInstanceMap, walkTree } from './components/tree'
+import { initUpdateTracking } from './components/update-tracking.js'
+import { getInstanceName } from './components/util'
+import { wrapVueForEvents } from './events'
+import { setupPlugin } from './plugin'
+
+export const backend = defineBackend({
+ frameworkVersion: 2,
+ features: [
+ BuiltinBackendFeature.FLUSH,
+ ],
+ setup(api) {
+ api.on.getAppRecordName((payload) => {
+ if (payload.app.name) {
+ payload.name = payload.app.name
+ }
+ else if (payload.app.$options.name) {
+ payload.name = payload.app.$options.name
+ }
+ })
+
+ api.on.getAppRootInstance((payload) => {
+ payload.root = payload.app as unknown as ComponentInstance
+ })
+
+ api.on.walkComponentTree(async (payload, ctx) => {
+ payload.componentTreeData = await walkTree(payload.componentInstance, payload.filter, payload.recursively, api, ctx)
+ })
+
+ api.on.walkComponentParents((payload, ctx) => {
+ payload.parentInstances = getComponentParents(payload.componentInstance, api, ctx)
+ })
+
+ api.on.inspectComponent((payload) => {
+ injectToUtils()
+ payload.instanceData = getInstanceDetails(payload.componentInstance)
+ })
+
+ api.on.getComponentBounds((payload) => {
+ payload.bounds = getInstanceOrVnodeRect(payload.componentInstance)
+ })
+
+ api.on.getComponentName((payload) => {
+ const instance = payload.componentInstance
+ payload.name = instance.fnContext ? getComponentName(instance.fnOptions) : getInstanceName(instance)
+ })
+
+ api.on.getElementComponent((payload) => {
+ payload.componentInstance = findRelatedComponent(payload.element)
+ })
+
+ api.on.editComponentState((payload) => {
+ editState(payload, api.stateEditor)
+ })
+
+ api.on.getComponentRootElements((payload) => {
+ payload.rootElements = getRootElementsFromComponentInstance(payload.componentInstance)
+ })
+
+ api.on.getComponentDevtoolsOptions((payload) => {
+ payload.options = payload.componentInstance.$options.devtools
+ })
+
+ api.on.getComponentRenderCode((payload) => {
+ payload.code = payload.componentInstance.$options.render.toString()
+ })
+
+ api.on.getComponentInstances(() => {
+ console.warn('on.getComponentInstances is not implemented for Vue 2')
+ })
+ },
+
+ setupApp(api, appRecord) {
+ const { Vue } = appRecord.options.meta
+ const app = appRecord.options.app
+
+ // State editor overrides
+ api.stateEditor.createDefaultSetCallback = (state) => {
+ return (obj, field, value) => {
+ if (state.remove || state.newKey) {
+ Vue.delete(obj, field)
+ }
+ if (!state.remove) {
+ Vue.set(obj, state.newKey || field, value)
+ }
+ }
+ }
+
+ // Utils
+ injectToUtils()
+ wrapVueForEvents(app, Vue, api.ctx)
+
+ // Plugin
+ setupPlugin(api, app, Vue)
+
+ // Perf
+ initPerf(api, app, Vue)
+ // Update tracking
+ initUpdateTracking(api, Vue)
+ },
+})
+
+// @TODO refactor
+function injectToUtils() {
+ backendInjections.getCustomInstanceDetails = getCustomInstanceDetails
+ backendInjections.getCustomObjectDetails = () => undefined
+ backendInjections.instanceMap = getInstanceMap()
+ backendInjections.isVueInstance = val => val._isVue
+}
diff --git a/vue-devtools/packages/app-backend-vue2/src/plugin.ts b/vue-devtools/packages/app-backend-vue2/src/plugin.ts
new file mode 100644
index 0000000000000000000000000000000000000000..40a4b24445389f1d33fa3281e18317d12bb85e9f
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue2/src/plugin.ts
@@ -0,0 +1,534 @@
+import type { DevtoolsApi } from '@vue-devtools/app-backend-api'
+import type { App, ComponentState, CustomInspectorNode, CustomInspectorState } from '@vue/devtools-api'
+import { setupDevtoolsPlugin } from '@vue/devtools-api'
+import { isEmptyObject, target } from '@vue-devtools/shared-utils'
+import copy from 'clone-deep'
+
+let actionId = 0
+
+const VUEX_ROOT_PATH = '__vdt_root'
+const VUEX_MODULE_PATH_SEPARATOR = '[vdt]'
+const VUEX_MODULE_PATH_SEPARATOR_REG = /\[vdt\]/g
+
+/**
+ * Extracted from tailwind palette
+ */
+const BLUE_600 = 0x2563EB
+const LIME_500 = 0x84CC16
+const CYAN_400 = 0x22D3EE
+const ORANGE_400 = 0xFB923C
+const WHITE = 0xFFFFFF
+const DARK = 0x666666
+
+export function setupPlugin(api: DevtoolsApi, app: App, Vue) {
+ const ROUTER_INSPECTOR_ID = 'vue2-router-inspector'
+ const ROUTER_CHANGES_LAYER_ID = 'vue2-router-changes'
+
+ const VUEX_INSPECTOR_ID = 'vue2-vuex-inspector'
+ const VUEX_MUTATIONS_ID = 'vue2-vuex-mutations'
+ const VUEX_ACTIONS_ID = 'vue2-vuex-actions'
+
+ setupDevtoolsPlugin({
+ app,
+ id: 'org.vuejs.vue2-internal',
+ label: 'Vue 2',
+ homepage: 'https://vuejs.org/',
+ logo: 'https://v2.vuejs.org/images/icons/favicon-96x96.png',
+ settings: {
+ legacyActions: {
+ label: 'Legacy Actions',
+ description: 'Enable this for Vuex < 3.1.0',
+ type: 'boolean',
+ defaultValue: false,
+ },
+ },
+ }, (api) => {
+ const hook = target.__VUE_DEVTOOLS_GLOBAL_HOOK__
+
+ // Vue Router
+ if (app.$router) {
+ const router = app.$router
+
+ // Inspector
+
+ api.addInspector({
+ id: ROUTER_INSPECTOR_ID,
+ label: 'Routes',
+ icon: 'book',
+ treeFilterPlaceholder: 'Search routes',
+ })
+
+ api.on.getInspectorTree((payload) => {
+ if (payload.inspectorId === ROUTER_INSPECTOR_ID) {
+ if (router.options.routes) {
+ payload.rootNodes = router.options.routes.map(route => formatRouteNode(router, route, '', payload.filter)).filter(Boolean)
+ }
+ else {
+ console.warn(`[Vue Devtools] No routes found in router`, router.options)
+ }
+ }
+ })
+
+ api.on.getInspectorState((payload) => {
+ if (payload.inspectorId === ROUTER_INSPECTOR_ID) {
+ const route = router.matcher.getRoutes().find(r => getPathId(r) === payload.nodeId)
+ if (route) {
+ payload.state = {
+ options: formatRouteData(route),
+ }
+ }
+ }
+ })
+
+ // Timeline
+
+ api.addTimelineLayer({
+ id: ROUTER_CHANGES_LAYER_ID,
+ label: 'Router Navigations',
+ color: 0x40A8C4,
+ })
+
+ router.afterEach((to, from) => {
+ api.addTimelineEvent({
+ layerId: ROUTER_CHANGES_LAYER_ID,
+ event: {
+ time: api.now(),
+ title: to.path,
+ data: {
+ from,
+ to,
+ },
+ },
+ })
+ api.sendInspectorTree(ROUTER_INSPECTOR_ID)
+ })
+ }
+
+ // Vuex
+ if (app.$store) {
+ const store = app.$store
+
+ api.addInspector({
+ id: VUEX_INSPECTOR_ID,
+ label: 'Vuex',
+ icon: 'storage',
+ treeFilterPlaceholder: 'Filter stores...',
+ })
+
+ api.on.getInspectorTree((payload) => {
+ if (payload.inspectorId === VUEX_INSPECTOR_ID) {
+ if (payload.filter) {
+ const nodes = []
+ flattenStoreForInspectorTree(nodes, store._modules.root, payload.filter, '')
+ payload.rootNodes = nodes
+ }
+ else {
+ payload.rootNodes = [
+ formatStoreForInspectorTree(store._modules.root, 'Root', ''),
+ ]
+ }
+ }
+ })
+
+ api.on.getInspectorState((payload) => {
+ if (payload.inspectorId === VUEX_INSPECTOR_ID) {
+ const modulePath = payload.nodeId
+ const { module, getterPath } = getStoreModule(store._modules, modulePath)
+ if (!module) {
+ return
+ }
+ // Access the getters prop to init getters cache (which is lazy)
+ // eslint-disable-next-line no-unused-expressions
+ module.context.getters
+ payload.state = formatStoreForInspectorState(
+ module,
+ store._makeLocalGettersCache,
+ getterPath,
+ )
+ }
+ })
+
+ api.on.editInspectorState((payload) => {
+ if (payload.inspectorId === VUEX_INSPECTOR_ID) {
+ let path = payload.path
+ if (payload.nodeId !== VUEX_ROOT_PATH) {
+ path = [
+ ...payload.nodeId.split(VUEX_MODULE_PATH_SEPARATOR).slice(0, -1),
+ ...path,
+ ]
+ }
+ store._committing = true
+ payload.set(store._vm.$data.$$state, path)
+ store._committing = false
+ }
+ })
+
+ api.addTimelineLayer({
+ id: VUEX_MUTATIONS_ID,
+ label: 'Vuex Mutations',
+ color: LIME_500,
+ })
+
+ api.addTimelineLayer({
+ id: VUEX_ACTIONS_ID,
+ label: 'Vuex Actions',
+ color: LIME_500,
+ })
+
+ hook.on('vuex:mutation', (mutation, state) => {
+ api.sendInspectorState(VUEX_INSPECTOR_ID)
+
+ const data: any = {}
+
+ if (mutation.payload) {
+ data.payload = mutation.payload
+ }
+
+ data.state = copy(state)
+
+ api.addTimelineEvent({
+ layerId: VUEX_MUTATIONS_ID,
+ event: {
+ time: api.now(),
+ title: mutation.type,
+ data,
+ },
+ })
+ })
+
+ function legacySingleActionSub(action, state) {
+ const data: any = {}
+ if (action.payload) {
+ data.payload = action.payload
+ }
+
+ data.state = state
+
+ api.addTimelineEvent({
+ layerId: VUEX_ACTIONS_ID,
+ event: {
+ time: api.now(),
+ title: action.type,
+ data,
+ },
+ })
+ }
+
+ store.subscribeAction?.(api.getSettings().legacyActions
+ ? legacySingleActionSub
+ : {
+ before: (action, state) => {
+ const data: any = {}
+ if (action.payload) {
+ data.payload = action.payload
+ }
+ action._id = actionId++
+ action._time = api.now()
+ data.state = state
+
+ api.addTimelineEvent({
+ layerId: VUEX_ACTIONS_ID,
+ event: {
+ time: action._time,
+ title: action.type,
+ groupId: action._id,
+ subtitle: 'start',
+ data,
+ },
+ })
+ },
+ after: (action, state) => {
+ const data: any = {}
+ const duration = api.now() - action._time
+ data.duration = {
+ _custom: {
+ type: 'duration',
+ display: `${duration}ms`,
+ tooltip: 'Action duration',
+ value: duration,
+ },
+ }
+ if (action.payload) {
+ data.payload = action.payload
+ }
+ data.state = state
+
+ api.addTimelineEvent({
+ layerId: VUEX_ACTIONS_ID,
+ event: {
+ time: api.now(),
+ title: action.type,
+ groupId: action._id,
+ subtitle: 'end',
+ data,
+ },
+ })
+ },
+ }, { prepend: true })
+
+ // Inspect getters on mutations
+ api.on.inspectTimelineEvent((payload) => {
+ if (payload.layerId === VUEX_MUTATIONS_ID) {
+ const getterKeys = Object.keys(store.getters)
+ if (getterKeys.length) {
+ const vm = new Vue({
+ data: {
+ $$state: payload.data.state,
+ },
+ computed: store._vm.$options.computed,
+ })
+ const originalVm = store._vm
+ store._vm = vm
+
+ const tree = transformPathsToObjectTree(store.getters)
+ payload.data.getters = copy(tree)
+
+ store._vm = originalVm
+ vm.$destroy()
+ }
+ }
+ })
+ }
+ })
+}
+
+function formatRouteNode(router, route, parentPath: string, filter: string): CustomInspectorNode {
+ const node: CustomInspectorNode = {
+ id: route.path.startsWith('/') ? route.path : `${parentPath}/${route.path}`,
+ label: route.path,
+ children: route.children?.map(child => formatRouteNode(router, child, route.path, filter)).filter(Boolean),
+ tags: [],
+ }
+
+ if (filter && !node.id.includes(filter) && !node.children?.length) {
+ return null
+ }
+
+ if (route.name != null) {
+ node.tags.push({
+ label: String(route.name),
+ textColor: 0,
+ backgroundColor: CYAN_400,
+ })
+ }
+
+ if (route.alias != null) {
+ node.tags.push({
+ label: 'alias',
+ textColor: 0,
+ backgroundColor: ORANGE_400,
+ })
+ }
+
+ if (node.id === router.currentRoute.path) {
+ node.tags.push({
+ label: 'active',
+ textColor: WHITE,
+ backgroundColor: BLUE_600,
+ })
+ }
+
+ if (route.redirect) {
+ node.tags.push({
+ label:
+ `redirect: ${
+ typeof route.redirect === 'string' ? route.redirect : 'Object'}`,
+ textColor: WHITE,
+ backgroundColor: DARK,
+ })
+ }
+
+ return node
+}
+
+function formatRouteData(route) {
+ const data: Omit[] = []
+
+ data.push({ key: 'path', value: route.path })
+
+ if (route.redirect) {
+ data.push({ key: 'redirect', value: route.redirect })
+ }
+
+ if (route.alias) {
+ data.push({ key: 'alias', value: route.alias })
+ }
+
+ if (route.props) {
+ data.push({ key: 'props', value: route.props })
+ }
+
+ if (route.name && route.name != null) {
+ data.push({ key: 'name', value: route.name })
+ }
+
+ if (route.component) {
+ const component: any = {}
+ // if (route.component.__file) {
+ // component.file = route.component.__file
+ // }
+ if (route.component.template) {
+ component.template = route.component.template
+ }
+ if (route.component.props) {
+ component.props = route.component.props
+ }
+ if (!isEmptyObject(component)) {
+ data.push({ key: 'component', value: component })
+ }
+ }
+
+ return data
+}
+
+function getPathId(routeMatcher) {
+ let path = routeMatcher.path
+ if (routeMatcher.parent) {
+ path = getPathId(routeMatcher.parent) + path
+ }
+ return path
+}
+
+const TAG_NAMESPACED = {
+ label: 'namespaced',
+ textColor: WHITE,
+ backgroundColor: DARK,
+}
+
+function formatStoreForInspectorTree(module, moduleName: string, path: string): CustomInspectorNode {
+ return {
+ id: path || VUEX_ROOT_PATH,
+ // all modules end with a `/`, we want the last segment only
+ // cart/ -> cart
+ // nested/cart/ -> cart
+ label: moduleName,
+ tags: module.namespaced ? [TAG_NAMESPACED] : [],
+ children: Object.keys(module._children ?? {}).map(key =>
+ formatStoreForInspectorTree(
+ module._children[key],
+ key,
+ `${path}${key}${VUEX_MODULE_PATH_SEPARATOR}`,
+ ),
+ ),
+ }
+}
+
+function flattenStoreForInspectorTree(result: CustomInspectorNode[], module, filter: string, path: string) {
+ if (path.includes(filter)) {
+ result.push({
+ id: path || VUEX_ROOT_PATH,
+ label: path.endsWith(VUEX_MODULE_PATH_SEPARATOR) ? path.slice(0, path.length - 1) : path || 'Root',
+ tags: module.namespaced ? [TAG_NAMESPACED] : [],
+ })
+ }
+ Object.keys(module._children).forEach((moduleName) => {
+ flattenStoreForInspectorTree(result, module._children[moduleName], filter, path + moduleName + VUEX_MODULE_PATH_SEPARATOR)
+ })
+}
+
+function extractNameFromPath(path: string) {
+ return path && path !== VUEX_ROOT_PATH ? path.split(VUEX_MODULE_PATH_SEPARATOR).slice(-2, -1)[0] : 'Root'
+}
+
+function formatStoreForInspectorState(module, getters, path): CustomInspectorState {
+ const storeState: CustomInspectorState = {
+ state: Object.keys(module.context.state ?? {}).map(key => ({
+ key,
+ editable: true,
+ value: module.context.state[key],
+ })),
+ }
+
+ if (getters) {
+ const pathWithSlashes = path.replace(VUEX_MODULE_PATH_SEPARATOR_REG, '/')
+ getters = !module.namespaced || path === VUEX_ROOT_PATH ? module.context.getters : getters[pathWithSlashes]
+ let gettersKeys = Object.keys(getters)
+ const shouldPickGetters = !module.namespaced && path !== VUEX_ROOT_PATH
+ if (shouldPickGetters) {
+ // Only pick the getters defined in the non-namespaced module
+ const definedGettersKeys = Object.keys(module._rawModule.getters ?? {})
+ gettersKeys = gettersKeys.filter(key => definedGettersKeys.includes(key))
+ }
+ if (gettersKeys.length) {
+ let moduleGetters: Record
+ if (shouldPickGetters) {
+ // Only pick the getters defined in the non-namespaced module
+ moduleGetters = {}
+ for (const key of gettersKeys) {
+ moduleGetters[key] = canThrow(() => getters[key])
+ }
+ }
+ else {
+ moduleGetters = getters
+ }
+ const tree = transformPathsToObjectTree(moduleGetters)
+ storeState.getters = Object.keys(tree).map(key => ({
+ key: key.endsWith('/') ? extractNameFromPath(key) : key,
+ editable: false,
+ value: canThrow(() => tree[key]),
+ }))
+ }
+ }
+
+ return storeState
+}
+
+function transformPathsToObjectTree(getters) {
+ const result = {}
+ Object.keys(getters).forEach((key) => {
+ const path = key.split('/')
+ if (path.length > 1) {
+ let target = result
+ const leafKey = path.pop()
+ for (const p of path) {
+ if (!target[p]) {
+ target[p] = {
+ _custom: {
+ value: {},
+ display: p,
+ tooltip: 'Module',
+ abstract: true,
+ },
+ }
+ }
+ target = target[p]._custom.value
+ }
+ target[leafKey] = canThrow(() => getters[key])
+ }
+ else {
+ result[key] = canThrow(() => getters[key])
+ }
+ })
+ return result
+}
+
+function getStoreModule(moduleMap, path) {
+ const names = path.split(VUEX_MODULE_PATH_SEPARATOR).filter(n => n)
+ return names.reduce(
+ ({ module, getterPath }, moduleName, i) => {
+ const child = module[moduleName === VUEX_ROOT_PATH ? 'root' : moduleName]
+ if (!child) {
+ return null
+ }
+ return {
+ module: i === names.length - 1 ? child : child._children,
+ getterPath: child._rawModule.namespaced
+ ? getterPath
+ : getterPath.replace(`${moduleName}${VUEX_MODULE_PATH_SEPARATOR}`, ''),
+ }
+ },
+ {
+ module: path === VUEX_ROOT_PATH ? moduleMap : moduleMap.root._children,
+ getterPath: path,
+ },
+ )
+}
+
+function canThrow(cb: () => any) {
+ try {
+ return cb()
+ }
+ catch (e) {
+ return e
+ }
+}
diff --git a/vue-devtools/packages/app-backend-vue2/tsconfig.json b/vue-devtools/packages/app-backend-vue2/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..becb763b20bbbd4557ba0717c957b4e3d3d6c81b
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue2/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "target": "ES2019",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "types": [
+ "node",
+ "webpack-env"
+ ],
+ "strictBindCallApply": true,
+ "strictFunctionTypes": true,
+ "alwaysStrict": true,
+ // Strict
+ "noImplicitAny": false,
+ "noImplicitThis": true,
+ "sourceMap": true,
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "preserveWatchOutput": true
+ },
+ "include": [
+ "src/**/*"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/vue-devtools/packages/app-backend-vue3/package.json b/vue-devtools/packages/app-backend-vue3/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..10e2e8a0379b581ef8c503118d31c32c9555411c
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue3/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "@vue-devtools/app-backend-vue3",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./lib/index.js",
+ "types": "./lib/index.d.ts",
+ "scripts": {
+ "build": "rimraf lib && yarn ts",
+ "build:watch": "yarn ts -w",
+ "ts": "tsc -d -outDir lib"
+ },
+ "dependencies": {
+ "@vue-devtools/app-backend-api": "^0.0.0",
+ "@vue-devtools/shared-utils": "^0.0.0",
+ "@vue/devtools-api": "^6.0.0-beta.1"
+ },
+ "devDependencies": {
+ "@types/node": "^20.11.16",
+ "@types/webpack-env": "^1.15.1",
+ "typescript": "^5.3.3"
+ }
+}
diff --git a/vue-devtools/packages/app-backend-vue3/src/components/data.ts b/vue-devtools/packages/app-backend-vue3/src/components/data.ts
new file mode 100644
index 0000000000000000000000000000000000000000..73edb754669fa1f20e0062b987e340ca0ba4d735
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue3/src/components/data.ts
@@ -0,0 +1,522 @@
+import type { BackendContext } from '@vue-devtools/app-backend-api'
+import type { StateEditor } from '@vue-devtools/shared-utils'
+import { SharedData, camelize, kebabize } from '@vue-devtools/shared-utils'
+import type { ComponentInstance, CustomState, HookPayloads, Hooks, InspectedComponentData } from '@vue/devtools-api'
+import { returnError } from '../util'
+import { getInstanceName, getUniqueComponentId } from './util'
+
+const vueBuiltins = [
+ 'nextTick',
+ 'defineComponent',
+ 'defineAsyncComponent',
+ 'defineCustomElement',
+ 'ref',
+ 'computed',
+ 'reactive',
+ 'readonly',
+ 'watchEffect',
+ 'watchPostEffect',
+ 'watchSyncEffect',
+ 'watch',
+ 'isRef',
+ 'unref',
+ 'toRef',
+ 'toRefs',
+ 'isProxy',
+ 'isReactive',
+ 'isReadonly',
+ 'shallowRef',
+ 'triggerRef',
+ 'customRef',
+ 'shallowReactive',
+ 'shallowReadonly',
+ 'toRaw',
+ 'markRaw',
+ 'effectScope',
+ 'getCurrentScope',
+ 'onScopeDispose',
+ 'onMounted',
+ 'onUpdated',
+ 'onUnmounted',
+ 'onBeforeMount',
+ 'onBeforeUpdate',
+ 'onBeforeUnmount',
+ 'onErrorCaptured',
+ 'onRenderTracked',
+ 'onRenderTriggered',
+ 'onActivated',
+ 'onDeactivated',
+ 'onServerPrefetch',
+ 'provide',
+ 'inject',
+ 'h',
+ 'mergeProps',
+ 'cloneVNode',
+ 'isVNode',
+ 'resolveComponent',
+ 'resolveDirective',
+ 'withDirectives',
+ 'withModifiers',
+]
+
+/**
+ * Get the detailed information of an inspected instance.
+ */
+export function getInstanceDetails(instance: any, ctx: BackendContext): InspectedComponentData {
+ return {
+ id: getUniqueComponentId(instance, ctx),
+ name: getInstanceName(instance),
+ file: instance.type?.__file,
+ state: getInstanceState(instance),
+ }
+}
+
+function getInstanceState(instance) {
+ const mergedType = resolveMergedOptions(instance)
+ return processProps(instance).concat(
+ processState(instance),
+ processSetupState(instance),
+ processComputed(instance, mergedType),
+ processAttrs(instance),
+ processProvide(instance),
+ processInject(instance, mergedType),
+ processRefs(instance),
+ processEventListeners(instance),
+ )
+}
+
+/**
+ * Process the props of an instance.
+ * Make sure return a plain object because window.postMessage()
+ * will throw an Error if the passed object contains Functions.
+ *
+ * @param {Vue} instance
+ * @return {Array}
+ */
+function processProps(instance) {
+ const propsData = []
+ const propDefinitions = instance.type.props
+
+ for (let key in instance.props) {
+ const propDefinition = propDefinitions ? propDefinitions[key] : null
+ key = camelize(key)
+ propsData.push({
+ type: 'props',
+ key,
+ value: returnError(() => instance.props[key]),
+ meta: propDefinition
+ ? {
+ type: propDefinition.type ? getPropType(propDefinition.type) : 'any',
+ required: !!propDefinition.required,
+ ...propDefinition.default != null
+ ? {
+ default: propDefinition.default.toString(),
+ }
+ : {},
+ }
+ : {
+ type: 'invalid',
+ },
+ editable: SharedData.editableProps,
+ })
+ }
+ return propsData
+}
+
+const fnTypeRE = /^(?:function|class) (\w+)/
+/**
+ * Convert prop type constructor to string.
+ */
+function getPropType(type) {
+ if (Array.isArray(type)) {
+ return type.map(t => getPropType(t)).join(' or ')
+ }
+ if (type == null) {
+ return 'null'
+ }
+ const match = type.toString().match(fnTypeRE)
+ return typeof type === 'function'
+ ? (match && match[1]) || 'any'
+ : 'any'
+}
+
+/**
+ * Process state, filtering out props and "clean" the result
+ * with a JSON dance. This removes functions which can cause
+ * errors during structured clone used by window.postMessage.
+ *
+ * @param {Vue} instance
+ * @return {Array}
+ */
+
+function processState(instance) {
+ const type = instance.type
+ const props = type.props
+ const getters
+ = type.vuex
+ && type.vuex.getters
+ const computedDefs = type.computed
+
+ const data = {
+ ...instance.data,
+ ...instance.renderContext,
+ }
+
+ return Object.keys(data)
+ .filter(key => (
+ !(props && key in props)
+ && !(getters && key in getters)
+ && !(computedDefs && key in computedDefs)
+ ))
+ .map(key => ({
+ key,
+ type: 'data',
+ value: returnError(() => data[key]),
+ editable: true,
+ }))
+}
+
+function processSetupState(instance) {
+ const raw = instance.devtoolsRawSetupState
+ const combinedSetupState = (Object.keys(instance.setupState).length
+ ? instance.setupState
+ : instance.exposed
+ ) || {}
+
+ return Object.keys(combinedSetupState)
+ .filter(key => !vueBuiltins.includes(key) && key.split(/(?=[A-Z])/)[0] !== 'use')
+ .map((key) => {
+ const value = returnError(() => toRaw(combinedSetupState[key]))
+
+ const rawData = raw[key]
+
+ let result: any
+
+ let isOther = typeof value === 'function'
+ || typeof value?.render === 'function' // Components
+ || typeof value?.__asyncLoader === 'function' // Components
+ || (typeof value === 'object' && value && ('setup' in value || 'props' in value)) // Components
+ || /^v[A-Z]/.test(key) // Directives
+
+ if (rawData) {
+ const info = getSetupStateInfo(rawData)
+
+ const objectType = info.computed ? 'Computed' : info.ref ? 'Ref' : info.reactive ? 'Reactive' : null
+ const isState = info.ref || info.computed || info.reactive
+ const raw = rawData.effect?.raw?.toString() || rawData.effect?.fn?.toString()
+
+ if (objectType) {
+ isOther = false
+ }
+
+ result = {
+ ...objectType ? { objectType } : {},
+ ...raw ? { raw } : {},
+ editable: isState && !info.readonly,
+ }
+ }
+
+ const type = isOther ? 'setup (other)' : 'setup'
+
+ return {
+ key,
+ value,
+ type,
+ ...result,
+ }
+ })
+}
+
+function isRef(raw: any): boolean {
+ return !!raw.__v_isRef
+}
+
+function isComputed(raw: any): boolean {
+ return isRef(raw) && !!raw.effect
+}
+
+function isReactive(raw: any): boolean {
+ return !!raw.__v_isReactive
+}
+
+function isReadOnly(raw: any): boolean {
+ return !!raw.__v_isReadonly
+}
+
+function toRaw(value: any) {
+ if (value?.__v_raw) {
+ return value.__v_raw
+ }
+ return value
+}
+
+function getSetupStateInfo(raw: any) {
+ return {
+ ref: isRef(raw),
+ computed: isComputed(raw),
+ reactive: isReactive(raw),
+ readonly: isReadOnly(raw),
+ }
+}
+
+export function getCustomObjectDetails(object: any, _proto: string): CustomState | undefined {
+ const info = getSetupStateInfo(object)
+
+ const isState = info.ref || info.computed || info.reactive
+ if (isState) {
+ const objectType = info.computed ? 'Computed' : info.ref ? 'Ref' : info.reactive ? 'Reactive' : null
+ const value = toRaw(info.reactive ? object : object._value)
+ const raw = object.effect?.raw?.toString() || object.effect?.fn?.toString()
+ return {
+ _custom: {
+ type: objectType.toLowerCase(),
+ objectType,
+ value,
+ ...raw ? { tooltip: `${raw}` } : {},
+ },
+ }
+ }
+
+ if (typeof object.__asyncLoader === 'function') {
+ return {
+ _custom: {
+ type: 'component-definition',
+ display: 'Async component definition',
+ },
+ }
+ }
+}
+
+/**
+ * Process the computed properties of an instance.
+ *
+ * @param {Vue} instance
+ * @return {Array}
+ */
+function processComputed(instance, mergedType) {
+ const type = mergedType
+ const computed = []
+ const defs = type.computed || {}
+ // use for...in here because if 'computed' is not defined
+ // on component, computed properties will be placed in prototype
+ // and Object.keys does not include
+ // properties from object's prototype
+ for (const key in defs) {
+ const def = defs[key]
+ const type = typeof def === 'function' && def.vuex
+ ? 'vuex bindings'
+ : 'computed'
+ computed.push({
+ type,
+ key,
+ value: returnError(() => instance.proxy[key]),
+ editable: typeof def.set === 'function',
+ })
+ }
+
+ return computed
+}
+
+function processAttrs(instance) {
+ return Object.keys(instance.attrs)
+ .map(key => ({
+ type: 'attrs',
+ key,
+ value: returnError(() => instance.attrs[key]),
+ }))
+}
+
+function processProvide(instance) {
+ return Reflect.ownKeys(instance.provides)
+ .map(key => ({
+ type: 'provided',
+ key: key.toString(),
+ value: returnError(() => instance.provides[key]),
+ }))
+}
+
+function processInject(instance, mergedType) {
+ if (!mergedType?.inject) {
+ return []
+ }
+ let keys = []
+ let defaultValue
+ if (Array.isArray(mergedType.inject)) {
+ keys = mergedType.inject.map(key => ({
+ key,
+ originalKey: key,
+ }))
+ }
+ else {
+ keys = Reflect.ownKeys(mergedType.inject).map((key) => {
+ const value = mergedType.inject[key]
+ let originalKey
+ if (typeof value === 'string' || typeof value === 'symbol') {
+ originalKey = value
+ }
+ else {
+ originalKey = value.from
+ defaultValue = value.default
+ }
+ return {
+ key,
+ originalKey,
+ }
+ })
+ }
+ return keys.map(({ key, originalKey }) => ({
+ type: 'injected',
+ key: originalKey && key !== originalKey ? `${originalKey.toString()} ➞ ${key.toString()}` : key.toString(),
+ value: returnError(() => Object.prototype.hasOwnProperty.call(instance.ctx, key) ? instance.ctx[key] : Object.prototype.hasOwnProperty.call(instance.provides, originalKey) ? instance.provides[originalKey] : defaultValue),
+ }))
+}
+
+function processRefs(instance) {
+ return Object.keys(instance.refs)
+ .map(key => ({
+ type: 'refs',
+ key,
+ value: returnError(() => instance.refs[key]),
+ }))
+}
+
+function processEventListeners(instance) {
+ const emitsDefinition = instance.type.emits
+ const declaredEmits = Array.isArray(emitsDefinition) ? emitsDefinition : Object.keys(emitsDefinition ?? {})
+ const declaredEmitsMap = declaredEmits.reduce((emitsMap, key) => {
+ emitsMap[kebabize(key)] = key
+ return emitsMap
+ }, {})
+ const keys = Object.keys(instance.vnode.props ?? {})
+ const result = []
+ for (const key of keys) {
+ const [prefix, ...eventNameParts] = key.split(/(?=[A-Z])/)
+ if (prefix === 'on') {
+ const eventName = eventNameParts.join('-').toLowerCase()
+ const normalizedEventName = declaredEmitsMap[eventName]
+ result.push({
+ type: 'event listeners',
+ key: normalizedEventName || eventName,
+ value: {
+ _custom: {
+ display: normalizedEventName ? '✅ Declared' : '⚠️ Not declared',
+ tooltip: !normalizedEventName ? `The event ${eventName}
is not declared in the emits
option. It will leak into the component's attributes ($attrs
).` : null,
+ },
+ },
+ })
+ }
+ }
+ return result
+}
+
+export function editState({ componentInstance, path, state, type }: HookPayloads[Hooks.EDIT_COMPONENT_STATE], stateEditor: StateEditor, _ctx: BackendContext) {
+ if (!['data', 'props', 'computed', 'setup'].includes(type)) {
+ return
+ }
+ let target: any
+ const targetPath: string[] = path.slice()
+
+ if (Object.keys(componentInstance.props).includes(path[0])) {
+ // Props
+ target = componentInstance.props
+ }
+ else if (componentInstance.devtoolsRawSetupState && Object.keys(componentInstance.devtoolsRawSetupState).includes(path[0])) {
+ // Setup
+ target = componentInstance.devtoolsRawSetupState
+
+ const currentValue = stateEditor.get(componentInstance.devtoolsRawSetupState, path)
+ if (currentValue != null) {
+ const info = getSetupStateInfo(currentValue)
+ if (info.readonly) {
+ return
+ }
+ }
+ }
+ else {
+ target = componentInstance.proxy
+ }
+
+ if (target && targetPath) {
+ stateEditor.set(target, targetPath, 'value' in state ? state.value : undefined, stateEditor.createDefaultSetCallback(state))
+ }
+}
+
+function reduceStateList(list) {
+ if (!list.length) {
+ return undefined
+ }
+ return list.reduce((map, item) => {
+ const key = item.type || 'data'
+ const obj = map[key] = map[key] || {}
+ obj[item.key] = item.value
+ return map
+ }, {})
+}
+
+export function getCustomInstanceDetails(instance) {
+ if (instance._) {
+ instance = instance._
+ }
+ const state = getInstanceState(instance)
+ return {
+ _custom: {
+ type: 'component',
+ id: instance.__VUE_DEVTOOLS_UID__,
+ display: getInstanceName(instance),
+ tooltip: 'Component instance',
+ value: reduceStateList(state),
+ fields: {
+ abstract: true,
+ },
+ },
+ }
+}
+
+function resolveMergedOptions(
+ instance: ComponentInstance,
+) {
+ const raw = instance.type
+ const { mixins, extends: extendsOptions } = raw
+ const globalMixins = instance.appContext.mixins
+ if (!globalMixins.length && !mixins && !extendsOptions) {
+ return raw
+ }
+ const options = {}
+ globalMixins.forEach(m => mergeOptions(options, m, instance))
+ mergeOptions(options, raw, instance)
+ return options
+}
+
+function mergeOptions(
+ to: any,
+ from: any,
+ instance: ComponentInstance,
+) {
+ if (typeof from === 'function') {
+ from = from.options
+ }
+
+ if (!from) {
+ return to
+ }
+
+ const { mixins, extends: extendsOptions } = from
+
+ extendsOptions && mergeOptions(to, extendsOptions, instance)
+ mixins
+ && mixins.forEach(m =>
+ mergeOptions(to, m, instance),
+ )
+
+ for (const key of ['computed', 'inject']) {
+ if (Object.prototype.hasOwnProperty.call(from, key)) {
+ if (!to[key]) {
+ to[key] = from[key]
+ }
+ else {
+ to[key] = Object.assign(Object.create(null), to[key], from[key])
+ }
+ }
+ }
+ return to
+}
diff --git a/vue-devtools/packages/app-backend-vue3/src/components/el.ts b/vue-devtools/packages/app-backend-vue3/src/components/el.ts
new file mode 100644
index 0000000000000000000000000000000000000000..442a26e533b27f89a4ec03b9e7742ec46c76016b
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue3/src/components/el.ts
@@ -0,0 +1,161 @@
+import { inDoc, isBrowser } from '@vue-devtools/shared-utils'
+import { isFragment } from './util'
+
+export function getComponentInstanceFromElement(element) {
+ return element.__vueParentComponent
+}
+
+export function getRootElementsFromComponentInstance(instance) {
+ if (isFragment(instance)) {
+ return getFragmentRootElements(instance.subTree)
+ }
+ if (!instance.subTree) {
+ return []
+ }
+ return [instance.subTree.el]
+}
+
+function getFragmentRootElements(vnode): any[] {
+ if (!vnode.children) {
+ return []
+ }
+
+ const list = []
+
+ for (let i = 0, l = vnode.children.length; i < l; i++) {
+ const childVnode = vnode.children[i]
+ if (childVnode.component) {
+ list.push(...getRootElementsFromComponentInstance(childVnode.component))
+ }
+ else if (childVnode.el) {
+ list.push(childVnode.el)
+ }
+ }
+
+ return list
+}
+
+/**
+ * Get the client rect for an instance.
+ *
+ * @param {Vue|Vnode} instance
+ * @return {object}
+ */
+export function getInstanceOrVnodeRect(instance) {
+ const el = instance.subTree.el
+
+ if (!isBrowser) {
+ // @TODO: Find position from instance or a vnode (for functional components).
+ return
+ }
+ if (!inDoc(el)) {
+ return
+ }
+
+ if (isFragment(instance)) {
+ return addIframePosition(getFragmentRect(instance.subTree), getElWindow(el))
+ }
+ else if (el.nodeType === 1) {
+ return addIframePosition(el.getBoundingClientRect(), getElWindow(el))
+ }
+ else if (instance.subTree.component) {
+ return getInstanceOrVnodeRect(instance.subTree.component)
+ }
+}
+
+function createRect() {
+ const rect = {
+ top: 0,
+ bottom: 0,
+ left: 0,
+ right: 0,
+ get width() { return rect.right - rect.left },
+ get height() { return rect.bottom - rect.top },
+ }
+ return rect
+}
+
+function mergeRects(a, b) {
+ if (!a.top || b.top < a.top) {
+ a.top = b.top
+ }
+ if (!a.bottom || b.bottom > a.bottom) {
+ a.bottom = b.bottom
+ }
+ if (!a.left || b.left < a.left) {
+ a.left = b.left
+ }
+ if (!a.right || b.right > a.right) {
+ a.right = b.right
+ }
+ return a
+}
+
+let range
+/**
+ * Get the bounding rect for a text node using a Range.
+ *
+ * @param {Text} node
+ * @return {Rect}
+ */
+function getTextRect(node) {
+ if (!isBrowser) {
+ return
+ }
+ if (!range) {
+ range = document.createRange()
+ }
+
+ range.selectNode(node)
+
+ return range.getBoundingClientRect()
+}
+
+function getFragmentRect(vnode) {
+ const rect = createRect()
+ if (!vnode.children) {
+ return rect
+ }
+
+ for (let i = 0, l = vnode.children.length; i < l; i++) {
+ const childVnode = vnode.children[i]
+ let childRect
+ if (childVnode.component) {
+ childRect = getInstanceOrVnodeRect(childVnode.component)
+ }
+ else if (childVnode.el) {
+ const el = childVnode.el
+ if (el.nodeType === 1 || el.getBoundingClientRect) {
+ childRect = el.getBoundingClientRect()
+ }
+ else if (el.nodeType === 3 && el.data.trim()) {
+ childRect = getTextRect(el)
+ }
+ }
+ if (childRect) {
+ mergeRects(rect, childRect)
+ }
+ }
+
+ return rect
+}
+
+function getElWindow(el: HTMLElement) {
+ return el.ownerDocument.defaultView
+}
+
+function addIframePosition(bounds, win: any) {
+ if (win.__VUE_DEVTOOLS_IFRAME__) {
+ const rect = mergeRects(createRect(), bounds)
+ const iframeBounds = win.__VUE_DEVTOOLS_IFRAME__.getBoundingClientRect()
+ rect.top += iframeBounds.top
+ rect.bottom += iframeBounds.top
+ rect.left += iframeBounds.left
+ rect.right += iframeBounds.left
+ if (win.parent) {
+ return addIframePosition(rect, win.parent)
+ }
+ return rect
+ }
+ return bounds
+}
diff --git a/vue-devtools/packages/app-backend-vue3/src/components/filter.ts b/vue-devtools/packages/app-backend-vue3/src/components/filter.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b0fb5c118fb91ce9ce3fd8cab50497bfd6869475
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue3/src/components/filter.ts
@@ -0,0 +1,22 @@
+import { classify, kebabize } from '@vue-devtools/shared-utils'
+import { getInstanceName } from './util'
+
+export class ComponentFilter {
+ filter: string
+
+ constructor(filter: string) {
+ this.filter = filter || ''
+ }
+
+ /**
+ * Check if an instance is qualified.
+ *
+ * @param {Vue|Vnode} instance
+ * @return {boolean}
+ */
+ isQualified(instance) {
+ const name = getInstanceName(instance)
+ return classify(name).toLowerCase().includes(this.filter)
+ || kebabize(name).toLowerCase().includes(this.filter)
+ }
+}
diff --git a/vue-devtools/packages/app-backend-vue3/src/components/tree.ts b/vue-devtools/packages/app-backend-vue3/src/components/tree.ts
new file mode 100644
index 0000000000000000000000000000000000000000..283bd010eb68da2e24af88d480652c9c3274b280
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue3/src/components/tree.ts
@@ -0,0 +1,252 @@
+import type { BackendContext, DevtoolsApi } from '@vue-devtools/app-backend-api'
+import type { ComponentTreeNode } from '@vue/devtools-api'
+import { getInstanceName, getRenderKey, getUniqueComponentId, isBeingDestroyed, isFragment } from './util'
+import { ComponentFilter } from './filter'
+import { getRootElementsFromComponentInstance } from './el'
+
+export class ComponentWalker {
+ ctx: BackendContext
+ api: DevtoolsApi
+ maxDepth: number
+ recursively: boolean
+ componentFilter: ComponentFilter
+ // Dedupe instances
+ // Some instances may be both on a component and on a child abstract/functional component
+ captureIds: Map
+
+ constructor(maxDepth: number, filter: string, recursively: boolean, api: DevtoolsApi, ctx: BackendContext) {
+ this.ctx = ctx
+ this.api = api
+ this.maxDepth = maxDepth
+ this.recursively = recursively
+ this.componentFilter = new ComponentFilter(filter)
+ }
+
+ getComponentTree(instance: any): Promise {
+ this.captureIds = new Map()
+ return this.findQualifiedChildren(instance, 0)
+ }
+
+ getComponentParents(instance: any) {
+ this.captureIds = new Map()
+ const parents = []
+ this.captureId(instance)
+ let parent = instance
+ // eslint-disable-next-line no-cond-assign
+ while ((parent = parent.parent)) {
+ this.captureId(parent)
+ parents.push(parent)
+ }
+ return parents
+ }
+
+ /**
+ * Find qualified children from a single instance.
+ * If the instance itself is qualified, just return itself.
+ * This is ok because [].concat works in both cases.
+ *
+ * @param {Vue|Vnode} instance
+ * @return {Vue|Array}
+ */
+ private async findQualifiedChildren(instance: any, depth: number): Promise {
+ if (this.componentFilter.isQualified(instance) && !instance.type.devtools?.hide) {
+ return [await this.capture(instance, null, depth)]
+ }
+ else if (instance.subTree) {
+ // TODO functional components
+ const list = this.isKeepAlive(instance)
+ ? this.getKeepAliveCachedInstances(instance)
+ : this.getInternalInstanceChildren(instance.subTree)
+ return this.findQualifiedChildrenFromList(list, depth)
+ }
+ else {
+ return []
+ }
+ }
+
+ /**
+ * Iterate through an array of instances and flatten it into
+ * an array of qualified instances. This is a depth-first
+ * traversal - e.g. if an instance is not matched, we will
+ * recursively go deeper until a qualified child is found.
+ *
+ * @param {Array} instances
+ * @return {Array}
+ */
+ private async findQualifiedChildrenFromList(instances, depth: number): Promise {
+ instances = instances
+ .filter(child => !isBeingDestroyed(child) && !child.type.devtools?.hide)
+ if (!this.componentFilter.filter) {
+ return Promise.all(instances.map((child, index, list) => this.capture(child, list, depth)))
+ }
+ else {
+ return Array.prototype.concat.apply([], await Promise.all(instances.map(i => this.findQualifiedChildren(i, depth))))
+ }
+ }
+
+ /**
+ * Get children from a component instance.
+ */
+ private getInternalInstanceChildren(subTree, suspense = null) {
+ const list = []
+ if (subTree) {
+ if (subTree.component) {
+ !suspense ? list.push(subTree.component) : list.push({ ...subTree.component, suspense })
+ }
+ else if (subTree.suspense) {
+ const suspenseKey = !subTree.suspense.isInFallback ? 'suspense default' : 'suspense fallback'
+ list.push(...this.getInternalInstanceChildren(subTree.suspense.activeBranch, { ...subTree.suspense, suspenseKey }))
+ }
+ else if (Array.isArray(subTree.children)) {
+ subTree.children.forEach((childSubTree) => {
+ if (childSubTree.component) {
+ !suspense ? list.push(childSubTree.component) : list.push({ ...childSubTree.component, suspense })
+ }
+ else {
+ list.push(...this.getInternalInstanceChildren(childSubTree, suspense))
+ }
+ })
+ }
+ }
+ return list.filter(child => !isBeingDestroyed(child) && !child.type.devtools?.hide)
+ }
+
+ private captureId(instance): string {
+ if (!instance) {
+ return null
+ }
+
+ // instance.uid is not reliable in devtools as there
+ // may be 2 roots with same uid which causes unexpected
+ // behaviour
+ const id = instance.__VUE_DEVTOOLS_UID__ != null ? instance.__VUE_DEVTOOLS_UID__ : getUniqueComponentId(instance, this.ctx)
+ instance.__VUE_DEVTOOLS_UID__ = id
+
+ // Dedupe
+ if (this.captureIds.has(id)) {
+ return
+ }
+ else {
+ this.captureIds.set(id, undefined)
+ }
+
+ this.mark(instance)
+
+ return id
+ }
+
+ /**
+ * Capture the meta information of an instance. (recursive)
+ *
+ * @param {Vue} instance
+ * @return {object}
+ */
+ private async capture(instance: any, list: any[], depth: number): Promise {
+ if (!instance) {
+ return null
+ }
+
+ const id = this.captureId(instance)
+
+ const name = getInstanceName(instance)
+
+ const children = this.getInternalInstanceChildren(instance.subTree)
+ .filter(child => !isBeingDestroyed(child))
+
+ const parents = this.getComponentParents(instance) || []
+
+ const inactive = !!instance.isDeactivated || parents.some(parent => parent.isDeactivated)
+
+ const treeNode: ComponentTreeNode = {
+ uid: instance.uid,
+ id,
+ name,
+ renderKey: getRenderKey(instance.vnode ? instance.vnode.key : null),
+ inactive,
+ hasChildren: !!children.length,
+ children: [],
+ isFragment: isFragment(instance),
+ tags: typeof instance.type !== 'function'
+ ? []
+ : [
+ {
+ label: 'functional',
+ textColor: 0x555555,
+ backgroundColor: 0xEEEEEE,
+ },
+ ],
+ autoOpen: this.recursively,
+ }
+
+ // capture children
+ if (depth < this.maxDepth || instance.type.__isKeepAlive || parents.some(parent => parent.type.__isKeepAlive)) {
+ treeNode.children = await Promise.all(children
+ .map((child, index, list) => this.capture(child, list, depth + 1))
+ .filter(Boolean))
+ }
+
+ // keep-alive
+ if (this.isKeepAlive(instance)) {
+ const cachedComponents = this.getKeepAliveCachedInstances(instance)
+ const childrenIds = children.map(child => child.__VUE_DEVTOOLS_UID__)
+ for (const cachedChild of cachedComponents) {
+ if (!childrenIds.includes(cachedChild.__VUE_DEVTOOLS_UID__)) {
+ const node = await this.capture({ ...cachedChild, isDeactivated: true }, null, depth + 1)
+ if (node) {
+ treeNode.children.push(node)
+ }
+ }
+ }
+ }
+
+ // ensure correct ordering
+ const rootElements = getRootElementsFromComponentInstance(instance)
+ const firstElement = rootElements[0]
+ if (firstElement?.parentElement) {
+ const parentInstance = instance.parent
+ const parentRootElements = parentInstance ? getRootElementsFromComponentInstance(parentInstance) : []
+ let el = firstElement
+ const indexList = []
+ do {
+ indexList.push(Array.from(el.parentElement.childNodes).indexOf(el))
+ el = el.parentElement
+ } while (el.parentElement && parentRootElements.length && !parentRootElements.includes(el))
+ treeNode.domOrder = indexList.reverse()
+ }
+ else {
+ treeNode.domOrder = [-1]
+ }
+
+ if (instance.suspense?.suspenseKey) {
+ treeNode.tags.push({
+ label: instance.suspense.suspenseKey,
+ backgroundColor: 0xE492E4,
+ textColor: 0xFFFFFF,
+ })
+ // update instanceMap
+ this.mark(instance, true)
+ }
+
+ return this.api.visitComponentTree(instance, treeNode, this.componentFilter.filter, this.ctx.currentAppRecord.options.app)
+ }
+
+ /**
+ * Mark an instance as captured and store it in the instance map.
+ *
+ * @param {Vue} instance
+ */
+ private mark(instance, force = false) {
+ const instanceMap = this.ctx.currentAppRecord.instanceMap
+ if (force || !instanceMap.has(instance.__VUE_DEVTOOLS_UID__)) {
+ instanceMap.set(instance.__VUE_DEVTOOLS_UID__, instance)
+ }
+ }
+
+ private isKeepAlive(instance) {
+ return instance.type.__isKeepAlive && instance.__v_cache
+ }
+
+ private getKeepAliveCachedInstances(instance) {
+ return Array.from(instance.__v_cache.values()).map((vnode: any) => vnode.component).filter(Boolean)
+ }
+}
diff --git a/vue-devtools/packages/app-backend-vue3/src/components/util.ts b/vue-devtools/packages/app-backend-vue3/src/components/util.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4fb1b0d3c7111822592cb4ba4081de306a1706f1
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue3/src/components/util.ts
@@ -0,0 +1,104 @@
+import { basename, classify } from '@vue-devtools/shared-utils'
+import type { App, ComponentInstance } from '@vue/devtools-api'
+import type { BackendContext } from '@vue-devtools/app-backend-api'
+
+export function isBeingDestroyed(instance) {
+ return instance._isBeingDestroyed || instance.isUnmounted
+}
+
+export function getAppRecord(instance) {
+ if (instance.root) {
+ return instance.appContext.app.__VUE_DEVTOOLS_APP_RECORD__
+ }
+}
+
+export function isFragment(instance) {
+ const appRecord = getAppRecord(instance)
+ if (appRecord) {
+ return appRecord.options.types.Fragment === instance.subTree?.type
+ }
+}
+
+/**
+ * Get the appropriate display name for an instance.
+ *
+ * @param {Vue} instance
+ * @return {string}
+ */
+export function getInstanceName(instance) {
+ const name = getComponentTypeName(instance.type || {})
+ if (name) {
+ return name
+ }
+ if (instance.root === instance) {
+ return 'Root'
+ }
+ for (const key in instance.parent?.type?.components) {
+ if (instance.parent.type.components[key] === instance.type) {
+ return saveComponentName(instance, key)
+ }
+ }
+ for (const key in instance.appContext?.components) {
+ if (instance.appContext.components[key] === instance.type) {
+ return saveComponentName(instance, key)
+ }
+ }
+ const fileName = getComponentFileName(instance.type || {})
+ if (fileName) {
+ return fileName
+ }
+ return 'Anonymous Component'
+}
+
+function saveComponentName(instance, key) {
+ instance.type.__vdevtools_guessedName = key
+ return key
+}
+
+function getComponentTypeName(options) {
+ return options.name || options._componentTag || options.__vdevtools_guessedName || options.__name
+}
+
+function getComponentFileName(options) {
+ const file = options.__file // injected by vue-loader
+ if (file) {
+ return classify(basename(file, '.vue'))
+ }
+}
+
+/**
+ * Returns a devtools unique id for instance.
+ * @param {Vue} instance
+ */
+export function getUniqueComponentId(instance, _ctx: BackendContext) {
+ const appId = instance.appContext.app.__VUE_DEVTOOLS_APP_RECORD_ID__
+ const instanceId = instance === instance.root ? 'root' : instance.uid
+ return `${appId}:${instanceId}`
+}
+
+export function getRenderKey(value): string {
+ if (value == null) {
+ return
+ }
+ const type = typeof value
+ if (type === 'number') {
+ return value
+ }
+ else if (type === 'string') {
+ return `'${value}'`
+ }
+ else if (Array.isArray(value)) {
+ return 'Array'
+ }
+ else {
+ return 'Object'
+ }
+}
+
+export function getComponentInstances(app: App): ComponentInstance[] {
+ const appRecord = app.__VUE_DEVTOOLS_APP_RECORD__
+ const appId = appRecord.id.toString()
+ return [...appRecord.instanceMap]
+ .filter(([key]) => key.split(':')[0] === appId)
+ .map(([,instance]) => instance)
+}
diff --git a/vue-devtools/packages/app-backend-vue3/src/index.ts b/vue-devtools/packages/app-backend-vue3/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b86cf5e2202e6b89984ce99f5e6a8d7f6bbf5fef
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue3/src/index.ts
@@ -0,0 +1,98 @@
+import { defineBackend } from '@vue-devtools/app-backend-api'
+import { HookEvents, backendInjections } from '@vue-devtools/shared-utils'
+import { ComponentWalker } from './components/tree'
+import { editState, getCustomInstanceDetails, getCustomObjectDetails, getInstanceDetails } from './components/data'
+import { getComponentInstances, getInstanceName } from './components/util'
+import { getComponentInstanceFromElement, getInstanceOrVnodeRect, getRootElementsFromComponentInstance } from './components/el'
+
+export const backend = defineBackend({
+ frameworkVersion: 3,
+
+ features: [],
+
+ setup(api) {
+ api.on.getAppRecordName((payload) => {
+ if (payload.app._component) {
+ payload.name = payload.app._component.name
+ }
+ })
+
+ api.on.getAppRootInstance((payload) => {
+ if (payload.app._instance) {
+ payload.root = payload.app._instance
+ }
+ else if (payload.app._container?._vnode?.component) {
+ payload.root = payload.app._container?._vnode?.component
+ }
+ })
+
+ api.on.walkComponentTree(async (payload, ctx) => {
+ const walker = new ComponentWalker(payload.maxDepth, payload.filter, payload.recursively, api, ctx)
+ payload.componentTreeData = await walker.getComponentTree(payload.componentInstance)
+ })
+
+ api.on.walkComponentParents((payload, ctx) => {
+ const walker = new ComponentWalker(0, null, false, api, ctx)
+ payload.parentInstances = walker.getComponentParents(payload.componentInstance)
+ })
+
+ api.on.inspectComponent((payload, ctx) => {
+ // @TODO refactor
+ backendInjections.getCustomInstanceDetails = getCustomInstanceDetails
+ backendInjections.getCustomObjectDetails = getCustomObjectDetails
+ backendInjections.instanceMap = ctx.currentAppRecord.instanceMap
+ backendInjections.isVueInstance = val => val._ && Object.keys(val._).includes('vnode')
+ payload.instanceData = getInstanceDetails(payload.componentInstance, ctx)
+ })
+
+ api.on.getComponentName((payload) => {
+ payload.name = getInstanceName(payload.componentInstance)
+ })
+
+ api.on.getComponentBounds((payload) => {
+ payload.bounds = getInstanceOrVnodeRect(payload.componentInstance)
+ })
+
+ api.on.getElementComponent((payload) => {
+ payload.componentInstance = getComponentInstanceFromElement(payload.element)
+ })
+
+ api.on.getComponentInstances((payload) => {
+ payload.componentInstances = getComponentInstances(payload.app)
+ })
+
+ api.on.getComponentRootElements((payload) => {
+ payload.rootElements = getRootElementsFromComponentInstance(payload.componentInstance)
+ })
+
+ api.on.editComponentState((payload, ctx) => {
+ editState(payload, api.stateEditor, ctx)
+ })
+
+ api.on.getComponentDevtoolsOptions((payload) => {
+ payload.options = payload.componentInstance.type.devtools
+ })
+
+ api.on.getComponentRenderCode((payload) => {
+ payload.code = !(payload.componentInstance.type instanceof Function) ? payload.componentInstance.render.toString() : payload.componentInstance.type.toString()
+ })
+
+ api.on.transformCall((payload) => {
+ if (payload.callName === HookEvents.COMPONENT_UPDATED) {
+ const component = payload.inArgs[0]
+ payload.outArgs = [
+ component.appContext.app,
+ component.uid,
+ component.parent ? component.parent.uid : undefined,
+ component,
+ ]
+ }
+ })
+
+ api.stateEditor.isRef = value => !!value?.__v_isRef
+ api.stateEditor.getRefValue = ref => ref.value
+ api.stateEditor.setRefValue = (ref, value) => {
+ ref.value = value
+ }
+ },
+})
diff --git a/vue-devtools/packages/app-backend-vue3/src/util.ts b/vue-devtools/packages/app-backend-vue3/src/util.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ebf171be0351d5f2b37d1f5ee86eb405018cd881
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue3/src/util.ts
@@ -0,0 +1,21 @@
+export function flatten(items) {
+ return items.reduce((acc, item) => {
+ if (Array.isArray(item)) {
+ acc.push(...flatten(item))
+ }
+ else if (item) {
+ acc.push(item)
+ }
+
+ return acc
+ }, [])
+}
+
+export function returnError(cb: () => any) {
+ try {
+ return cb()
+ }
+ catch (e) {
+ return e
+ }
+}
diff --git a/vue-devtools/packages/app-backend-vue3/tsconfig.json b/vue-devtools/packages/app-backend-vue3/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..becb763b20bbbd4557ba0717c957b4e3d3d6c81b
--- /dev/null
+++ b/vue-devtools/packages/app-backend-vue3/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "target": "ES2019",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "types": [
+ "node",
+ "webpack-env"
+ ],
+ "strictBindCallApply": true,
+ "strictFunctionTypes": true,
+ "alwaysStrict": true,
+ // Strict
+ "noImplicitAny": false,
+ "noImplicitThis": true,
+ "sourceMap": true,
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "preserveWatchOutput": true
+ },
+ "include": [
+ "src/**/*"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/vue-devtools/packages/app-frontend/package.json b/vue-devtools/packages/app-frontend/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..971ab0682311a639348b2b6d68dd70162302fddf
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "@vue-devtools/app-frontend",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "@pixi/events": "^6.2.0",
+ "@pixi/unsafe-eval": "^6.2.0",
+ "@vue-devtools/shared-utils": "^0.0.0",
+ "@vue/devtools-api": "^6.0.0-beta.9",
+ "@vue/ui": "^0.12.5",
+ "@vueuse/core": "^10.7.2",
+ "circular-json-es6": "^2.0.2",
+ "d3": "^5.16.0",
+ "floating-vue": "^5.2.2",
+ "lodash": "^4.17.15",
+ "lru-cache": "^5.1.1",
+ "monaco-editor": "^0.24.0",
+ "pixi.js-legacy": "^6.2.0",
+ "scroll-into-view-if-needed": "^2.2.28",
+ "semver": "^7.3.5",
+ "stylus": "^0.54.7",
+ "stylus-loader": "^3.0.2",
+ "tinycolor2": "^1.4.2",
+ "vue": "^3.3.4",
+ "vue-resize": "^2.0.0-alpha.1",
+ "vue-router": "^4.2.5",
+ "vue-safe-teleport": "^0.1.2",
+ "vue-virtual-scroller": "^2.0.0-alpha.1"
+ },
+ "devDependencies": {
+ "@akryum/md-icons-svg": "^1.0.1"
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/app.ts b/vue-devtools/packages/app-frontend/src/app.ts
new file mode 100644
index 0000000000000000000000000000000000000000..15da8110bceeae9b1d412b4abe51a57a5b164e38
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/app.ts
@@ -0,0 +1,84 @@
+import type { App as VueApp } from 'vue'
+import { createApp as createVueApp } from 'vue'
+import { BridgeEvents, SharedData, destroySharedData, initEnv, initSharedData, isChrome } from '@vue-devtools/shared-utils'
+import App from './features/App.vue'
+import { createRouterInstance } from './router'
+import { getBridge, setBridge } from './features/bridge'
+import { setAppConnected, setAppInitializing } from './features/connection'
+import { setupAppsBridgeEvents } from './features/apps'
+import { setupComponentsBridgeEvents } from './features/components/composable'
+import { setupTimelineBridgeEvents } from './features/timeline/composable'
+import { setupCustomInspectorBridgeEvents } from './features/inspector/custom/composable'
+import { setupPluginsBridgeEvents } from './features/plugin'
+import { setupPlugins } from './plugins'
+
+// Capture and log devtool errors when running as actual extension
+// so that we can debug it by inspecting the background page.
+// We do want the errors to be thrown in the dev shell though.
+export function createApp() {
+ const router = createRouterInstance()
+
+ const app = createVueApp(App)
+ app.use(router)
+ setupPlugins(app)
+
+ if (isChrome) {
+ app.config.errorHandler = (e, vm) => {
+ getBridge()?.send('ERROR', {
+ message: (e as Error).message,
+ stack: (e as Error).stack,
+ component: vm?.$options.name || (vm?.$options as any)._componentTag || 'anonymous',
+ })
+ }
+ }
+
+ return app
+}
+
+/**
+ * Connect then init the app. We need to reconnect on every reload, because a
+ * new backend will be injected.
+ */
+export function connectApp(app: VueApp, shell) {
+ shell.connect(async (bridge) => {
+ setBridge(bridge)
+ // @TODO remove
+ // @ts-expect-error custom prop on window
+ window.bridge = bridge
+
+ if (app.config.globalProperties.$shared) {
+ destroySharedData()
+ }
+ else {
+ Object.defineProperty(app.config.globalProperties, '$shared', {
+ get: () => SharedData,
+ })
+ }
+
+ initEnv(app)
+
+ bridge.on(BridgeEvents.TO_FRONT_TITLE, ({ title }: { title: string }) => {
+ document.title = `${title} - Vue devtools`
+ })
+
+ await initSharedData({
+ bridge,
+ persist: true,
+ })
+
+ if (SharedData.logDetected) {
+ bridge.send('log-detected-vue')
+ }
+
+ setupAppsBridgeEvents(bridge)
+ setupComponentsBridgeEvents(bridge)
+ setupTimelineBridgeEvents(bridge)
+ setupCustomInspectorBridgeEvents(bridge)
+ setupPluginsBridgeEvents(bridge)
+
+ // @TODO bridge listeners
+
+ setAppConnected(true)
+ setAppInitializing(false)
+ })
+}
diff --git a/vue-devtools/packages/app-frontend/src/assets/MaterialIcons-Regular.woff2 b/vue-devtools/packages/app-frontend/src/assets/MaterialIcons-Regular.woff2
new file mode 100644
index 0000000000000000000000000000000000000000..9fa211252080046a23b2449dbdced6abc2b0bb34
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/MaterialIcons-Regular.woff2 differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/Roboto-Mono.ttf b/vue-devtools/packages/app-frontend/src/assets/Roboto-Mono.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..9c3668e00bd9077adad7d35c7ec220c61d7427ae
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/assets/Roboto-Mono.ttf
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4f473afed897c2b96079c7be0727e0babc80bc396a79b1881f87a9a7ad38be6a
+size 182172
diff --git a/vue-devtools/packages/app-frontend/src/assets/Roboto-Regular.woff2 b/vue-devtools/packages/app-frontend/src/assets/Roboto-Regular.woff2
new file mode 100644
index 0000000000000000000000000000000000000000..9a0064ec27e069931227a628e8ed899f3dda2c73
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/Roboto-Regular.woff2 differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/breadcrumb-separator.svg b/vue-devtools/packages/app-frontend/src/assets/breadcrumb-separator.svg
new file mode 100644
index 0000000000000000000000000000000000000000..645b97f1d9ab288ed479a21c1c5a44b68861fb60
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/assets/breadcrumb-separator.svg
@@ -0,0 +1,3 @@
+
diff --git a/vue-devtools/packages/app-frontend/src/assets/devtools-logo.svg b/vue-devtools/packages/app-frontend/src/assets/devtools-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..9e07f99f88e77edb2d445176a86c8add6007ea8c
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/assets/devtools-logo.svg
@@ -0,0 +1,37 @@
+
+
diff --git a/vue-devtools/packages/app-frontend/src/assets/github-theme/dark.json b/vue-devtools/packages/app-frontend/src/assets/github-theme/dark.json
new file mode 100644
index 0000000000000000000000000000000000000000..84bf8ad012c438d467bb9656c27fd2122ddded55
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/assets/github-theme/dark.json
@@ -0,0 +1,535 @@
+{
+ "inherit": true,
+ "base": "vs-dark",
+ "colors": {
+ "focusBorder": "#388bfd",
+ "foreground": "#c9d1d9",
+ "descriptionForeground": "#8b949e",
+ "errorForeground": "#f85149",
+ "textLink.foreground": "#58a6ff",
+ "textLink.activeForeground": "#58a6ff",
+ "textBlockQuote.background": "#090c10",
+ "textBlockQuote.border": "#3b434b",
+ "textCodeBlock.background": "#f0f6fc26",
+ "textPreformat.foreground": "#8b949e",
+ "textSeparator.foreground": "#21262d",
+ "button.background": "#238636",
+ "button.foreground": "#ffffff",
+ "button.hoverBackground": "#2ea043",
+ "button.secondaryBackground": "#292e34",
+ "button.secondaryForeground": "#c9d1d9",
+ "button.secondaryHoverBackground": "#30363d",
+ "checkbox.background": "#161b22",
+ "checkbox.border": "#30363d",
+ "dropdown.background": "#1c2128",
+ "dropdown.border": "#30363d",
+ "dropdown.foreground": "#c9d1d9",
+ "dropdown.listBackground": "#1c2128",
+ "input.background": "#0d1117",
+ "input.border": "#21262d",
+ "input.foreground": "#c9d1d9",
+ "input.placeholderForeground": "#484f58",
+ "badge.foreground": "#79c0ff",
+ "badge.background": "#0d419d",
+ "progressBar.background": "#1f6feb",
+ "titleBar.activeForeground": "#8b949e",
+ "titleBar.activeBackground": "#0d1117",
+ "titleBar.inactiveForeground": "#8b949e",
+ "titleBar.inactiveBackground": "#090c10",
+ "titleBar.border": "#30363d",
+ "activityBar.foreground": "#c9d1d9",
+ "activityBar.inactiveForeground": "#8b949e",
+ "activityBar.background": "#0d1117",
+ "activityBarBadge.foreground": "#f0f6fc",
+ "activityBarBadge.background": "#1f6feb",
+ "activityBar.activeBorder": "#f78166",
+ "activityBar.border": "#30363d",
+ "sideBar.foreground": "#c9d1d9",
+ "sideBar.background": "#090c10",
+ "sideBar.border": "#30363d",
+ "sideBarTitle.foreground": "#c9d1d9",
+ "sideBarSectionHeader.foreground": "#c9d1d9",
+ "sideBarSectionHeader.background": "#090c10",
+ "sideBarSectionHeader.border": "#30363d",
+ "list.hoverForeground": "#c9d1d9",
+ "list.inactiveSelectionForeground": "#c9d1d9",
+ "list.activeSelectionForeground": "#c9d1d9",
+ "list.hoverBackground": "#161b22",
+ "list.inactiveSelectionBackground": "#161b22",
+ "list.activeSelectionBackground": "#21262d",
+ "list.focusForeground": "#f0f6fc",
+ "list.focusBackground": "#21262d",
+ "list.inactiveFocusBackground": "#161b22",
+ "list.highlightForeground": "#388bfd",
+ "tree.indentGuidesStroke": "#21262d",
+ "notificationCenterHeader.foreground": "#6e7681",
+ "notificationCenterHeader.background": "#0d1117",
+ "notifications.foreground": "#8b949e",
+ "notifications.background": "#161b22",
+ "notifications.border": "#30363d",
+ "notificationsErrorIcon.foreground": "#f85149",
+ "notificationsWarningIcon.foreground": "#f0883e",
+ "notificationsInfoIcon.foreground": "#58a6ff",
+ "pickerGroup.border": "#21262d",
+ "pickerGroup.foreground": "#8b949e",
+ "quickInput.background": "#0d1117",
+ "quickInput.foreground": "#c9d1d9",
+ "statusBar.foreground": "#8b949e",
+ "statusBar.background": "#0d1117",
+ "statusBar.border": "#30363d",
+ "statusBar.noFolderBackground": "#0d1117",
+ "statusBar.debuggingBackground": "#da3633",
+ "statusBar.debuggingForeground": "#f0f6fc",
+ "statusBarItem.prominentBackground": "#161b22",
+ "editorGroupHeader.tabsBackground": "#090c10",
+ "editorGroupHeader.tabsBorder": "#30363d",
+ "editorGroup.border": "#30363d",
+ "tab.activeForeground": "#c9d1d9",
+ "tab.inactiveForeground": "#8b949e",
+ "tab.inactiveBackground": "#090c10",
+ "tab.activeBackground": "#0d1117",
+ "tab.hoverBackground": "#0d1117",
+ "tab.unfocusedHoverBackground": "#161b22",
+ "tab.border": "#30363d",
+ "tab.unfocusedActiveBorderTop": "#30363d",
+ "tab.activeBorder": "#0d1117",
+ "tab.unfocusedActiveBorder": "#0d1117",
+ "tab.activeBorderTop": "#f78166",
+ "breadcrumb.foreground": "#8b949e",
+ "breadcrumb.focusForeground": "#c9d1d9",
+ "breadcrumb.activeSelectionForeground": "#8b949e",
+ "breadcrumbPicker.background": "#1c2128",
+ "editor.foreground": "#c9d1d9",
+ "editor.background": "#0d1117",
+ "editorWidget.background": "#1c2128",
+ "editor.foldBackground": "#6e76811a",
+ "editor.lineHighlightBackground": "#161b22",
+ "editorLineNumber.foreground": "#8b949e",
+ "editorLineNumber.activeForeground": "#c9d1d9",
+ "editorIndentGuide.background": "#21262d",
+ "editorIndentGuide.activeBackground": "#30363d",
+ "editorWhitespace.foreground": "#484f58",
+ "editorCursor.foreground": "#79c0ff",
+ "editor.findMatchBackground": "#ffd33d44",
+ "editor.findMatchHighlightBackground": "#ffd33d22",
+ "editor.linkedEditingBackground": "#3392FF22",
+ "editor.inactiveSelectionBackground": "#3392FF22",
+ "editor.selectionBackground": "#3392FF44",
+ "editor.selectionHighlightBackground": "#17E5E633",
+ "editor.selectionHighlightBorder": "#17E5E600",
+ "editor.wordHighlightBackground": "#17E5E600",
+ "editor.wordHighlightStrongBackground": "#17E5E600",
+ "editor.wordHighlightBorder": "#17E5E699",
+ "editor.wordHighlightStrongBorder": "#17E5E666",
+ "editorBracketMatch.background": "#17E5E650",
+ "editorBracketMatch.border": "#17E5E600",
+ "editorGutter.modifiedBackground": "#9e6a03",
+ "editorGutter.addedBackground": "#196c2e",
+ "editorGutter.deletedBackground": "#b62324",
+ "diffEditor.insertedTextBackground": "#2ea04333",
+ "diffEditor.removedTextBackground": "#da363333",
+ "scrollbar.shadow": "#0008",
+ "scrollbarSlider.background": "#484F5833",
+ "scrollbarSlider.hoverBackground": "#484F5844",
+ "scrollbarSlider.activeBackground": "#484F5888",
+ "editorOverviewRuler.border": "#010409",
+ "panel.background": "#090c10",
+ "panel.border": "#30363d",
+ "panelTitle.activeBorder": "#f78166",
+ "panelTitle.activeForeground": "#c9d1d9",
+ "panelTitle.inactiveForeground": "#8b949e",
+ "panelInput.border": "#30363d",
+ "terminal.foreground": "#8b949e",
+ "terminal.ansiBlack": "#484f58",
+ "terminal.ansiRed": "#ff7b72",
+ "terminal.ansiGreen": "#3fb950",
+ "terminal.ansiYellow": "#d29922",
+ "terminal.ansiBlue": "#58a6ff",
+ "terminal.ansiMagenta": "#bc8cff",
+ "terminal.ansiCyan": "#39c5cf",
+ "terminal.ansiWhite": "#b1bac4",
+ "terminal.ansiBrightBlack": "#6e7681",
+ "terminal.ansiBrightRed": "#ffa198",
+ "terminal.ansiBrightGreen": "#56d364",
+ "terminal.ansiBrightYellow": "#e3b341",
+ "terminal.ansiBrightBlue": "#79c0ff",
+ "terminal.ansiBrightMagenta": "#d2a8ff",
+ "terminal.ansiBrightCyan": "#56d4dd",
+ "terminal.ansiBrightWhite": "#f0f6fc",
+ "gitDecoration.addedResourceForeground": "#56d364",
+ "gitDecoration.modifiedResourceForeground": "#e3b341",
+ "gitDecoration.deletedResourceForeground": "#f85149",
+ "gitDecoration.untrackedResourceForeground": "#56d364",
+ "gitDecoration.ignoredResourceForeground": "#484f58",
+ "gitDecoration.conflictingResourceForeground": "#e3b341",
+ "gitDecoration.submoduleResourceForeground": "#8b949e",
+ "debugToolBar.background": "#1c2128",
+ "editor.stackFrameHighlightBackground": "#D2992225",
+ "editor.focusedStackFrameHighlightBackground": "#3FB95025",
+ "peekViewEditor.matchHighlightBackground": "#ffd33d33",
+ "peekViewResult.matchHighlightBackground": "#ffd33d33",
+ "peekViewEditor.background": "#0d111788",
+ "peekViewResult.background": "#0d1117",
+ "settings.headerForeground": "#8b949e",
+ "settings.modifiedItemIndicator": "#9e6a03",
+ "welcomePage.buttonBackground": "#21262d",
+ "welcomePage.buttonHoverBackground": "#30363d"
+ },
+ "rules": [
+ {
+ "foreground": "#8b949e",
+ "token": "comment"
+ },
+ {
+ "foreground": "#8b949e",
+ "token": "punctuation.definition.comment"
+ },
+ {
+ "foreground": "#8b949e",
+ "token": "string.comment"
+ },
+ {
+ "foreground": "#79c0ff",
+ "token": "constant"
+ },
+ {
+ "foreground": "#79c0ff",
+ "token": "entity.name.constant"
+ },
+ {
+ "foreground": "#79c0ff",
+ "token": "variable.other.constant"
+ },
+ {
+ "foreground": "#79c0ff",
+ "token": "variable.language"
+ },
+ {
+ "foreground": "#79c0ff",
+ "token": "entity"
+ },
+ {
+ "foreground": "#ffa657",
+ "token": "entity.name"
+ },
+ {
+ "foreground": "#ffa657",
+ "token": "meta.export.default"
+ },
+ {
+ "foreground": "#ffa657",
+ "token": "meta.definition.variable"
+ },
+ {
+ "foreground": "#c9d1d9",
+ "token": "variable.parameter.function"
+ },
+ {
+ "foreground": "#c9d1d9",
+ "token": "meta.jsx.children"
+ },
+ {
+ "foreground": "#c9d1d9",
+ "token": "meta.block"
+ },
+ {
+ "foreground": "#c9d1d9",
+ "token": "meta.tag.attributes"
+ },
+ {
+ "foreground": "#c9d1d9",
+ "token": "entity.name.constant"
+ },
+ {
+ "foreground": "#c9d1d9",
+ "token": "meta.object.member"
+ },
+ {
+ "foreground": "#c9d1d9",
+ "token": "meta.embedded.expression"
+ },
+ {
+ "foreground": "#d2a8ff",
+ "token": "entity.name.function"
+ },
+ {
+ "foreground": "#7ee787",
+ "token": "entity.name.tag"
+ },
+ {
+ "foreground": "#7ee787",
+ "token": "support.class.component"
+ },
+ {
+ "foreground": "#ff7b72",
+ "token": "keyword"
+ },
+ {
+ "foreground": "#ff7b72",
+ "token": "storage"
+ },
+ {
+ "foreground": "#ff7b72",
+ "token": "storage.type"
+ },
+ {
+ "foreground": "#c9d1d9",
+ "token": "storage.modifier.package"
+ },
+ {
+ "foreground": "#c9d1d9",
+ "token": "storage.modifier.import"
+ },
+ {
+ "foreground": "#c9d1d9",
+ "token": "storage.type.java"
+ },
+ {
+ "foreground": "#a5d6ff",
+ "token": "string"
+ },
+ {
+ "foreground": "#a5d6ff",
+ "token": "punctuation.definition.string"
+ },
+ {
+ "foreground": "#a5d6ff",
+ "token": "string punctuation.section.embedded source"
+ },
+ {
+ "foreground": "#79c0ff",
+ "token": "support"
+ },
+ {
+ "foreground": "#79c0ff",
+ "token": "meta.property-name"
+ },
+ {
+ "foreground": "#ffa657",
+ "token": "variable"
+ },
+ {
+ "foreground": "#c9d1d9",
+ "token": "variable.other"
+ },
+ {
+ "fontStyle": "italic",
+ "foreground": "#ffa198",
+ "token": "invalid.broken"
+ },
+ {
+ "fontStyle": "italic",
+ "foreground": "#ffa198",
+ "token": "invalid.deprecated"
+ },
+ {
+ "fontStyle": "italic",
+ "foreground": "#ffa198",
+ "token": "invalid.illegal"
+ },
+ {
+ "fontStyle": "italic",
+ "foreground": "#ffa198",
+ "token": "invalid.unimplemented"
+ },
+ {
+ "fontStyle": "italic underline",
+ "background": "#ff7b72",
+ "foreground": "#0d1117",
+ "content": "^M",
+ "token": "carriage-return"
+ },
+ {
+ "foreground": "#ffa198",
+ "token": "message.error"
+ },
+ {
+ "foreground": "#c9d1d9",
+ "token": "string source"
+ },
+ {
+ "foreground": "#79c0ff",
+ "token": "string variable"
+ },
+ {
+ "foreground": "#a5d6ff",
+ "token": "source.regexp"
+ },
+ {
+ "foreground": "#a5d6ff",
+ "token": "string.regexp"
+ },
+ {
+ "foreground": "#a5d6ff",
+ "token": "string.regexp.character-class"
+ },
+ {
+ "foreground": "#a5d6ff",
+ "token": "string.regexp constant.character.escape"
+ },
+ {
+ "foreground": "#a5d6ff",
+ "token": "string.regexp source.ruby.embedded"
+ },
+ {
+ "foreground": "#a5d6ff",
+ "token": "string.regexp string.regexp.arbitrary-repitition"
+ },
+ {
+ "fontStyle": "bold",
+ "foreground": "#7ee787",
+ "token": "string.regexp constant.character.escape"
+ },
+ {
+ "foreground": "#79c0ff",
+ "token": "support.constant"
+ },
+ {
+ "foreground": "#79c0ff",
+ "token": "support.variable"
+ },
+ {
+ "foreground": "#79c0ff",
+ "token": "meta.module-reference"
+ },
+ {
+ "foreground": "#ffa657",
+ "token": "punctuation.definition.list.begin.markdown"
+ },
+ {
+ "fontStyle": "bold",
+ "foreground": "#79c0ff",
+ "token": "markup.heading"
+ },
+ {
+ "fontStyle": "bold",
+ "foreground": "#79c0ff",
+ "token": "markup.heading entity.name"
+ },
+ {
+ "foreground": "#7ee787",
+ "token": "markup.quote"
+ },
+ {
+ "fontStyle": "italic",
+ "foreground": "#c9d1d9",
+ "token": "markup.italic"
+ },
+ {
+ "fontStyle": "bold",
+ "foreground": "#c9d1d9",
+ "token": "markup.bold"
+ },
+ {
+ "foreground": "#79c0ff",
+ "token": "markup.raw"
+ },
+ {
+ "background": "#490202",
+ "foreground": "#ffa198",
+ "token": "markup.deleted"
+ },
+ {
+ "background": "#490202",
+ "foreground": "#ffa198",
+ "token": "meta.diff.header.from-file"
+ },
+ {
+ "background": "#490202",
+ "foreground": "#ffa198",
+ "token": "punctuation.definition.deleted"
+ },
+ {
+ "background": "#04260f",
+ "foreground": "#7ee787",
+ "token": "markup.inserted"
+ },
+ {
+ "background": "#04260f",
+ "foreground": "#7ee787",
+ "token": "meta.diff.header.to-file"
+ },
+ {
+ "background": "#04260f",
+ "foreground": "#7ee787",
+ "token": "punctuation.definition.inserted"
+ },
+ {
+ "background": "#5a1e02",
+ "foreground": "#ffa657",
+ "token": "markup.changed"
+ },
+ {
+ "background": "#5a1e02",
+ "foreground": "#ffa657",
+ "token": "punctuation.definition.changed"
+ },
+ {
+ "foreground": "#161b22",
+ "background": "#79c0ff",
+ "token": "markup.ignored"
+ },
+ {
+ "foreground": "#161b22",
+ "background": "#79c0ff",
+ "token": "markup.untracked"
+ },
+ {
+ "foreground": "#d2a8ff",
+ "fontStyle": "bold",
+ "token": "meta.diff.range"
+ },
+ {
+ "foreground": "#79c0ff",
+ "token": "meta.diff.header"
+ },
+ {
+ "fontStyle": "bold",
+ "foreground": "#79c0ff",
+ "token": "meta.separator"
+ },
+ {
+ "foreground": "#79c0ff",
+ "token": "meta.output"
+ },
+ {
+ "foreground": "#8b949e",
+ "token": "brackethighlighter.tag"
+ },
+ {
+ "foreground": "#8b949e",
+ "token": "brackethighlighter.curly"
+ },
+ {
+ "foreground": "#8b949e",
+ "token": "brackethighlighter.round"
+ },
+ {
+ "foreground": "#8b949e",
+ "token": "brackethighlighter.square"
+ },
+ {
+ "foreground": "#8b949e",
+ "token": "brackethighlighter.angle"
+ },
+ {
+ "foreground": "#8b949e",
+ "token": "brackethighlighter.quote"
+ },
+ {
+ "foreground": "#ffa198",
+ "token": "brackethighlighter.unmatched"
+ },
+ {
+ "foreground": "#a5d6ff",
+ "fontStyle": "underline",
+ "token": "constant.other.reference.link"
+ },
+ {
+ "foreground": "#a5d6ff",
+ "fontStyle": "underline",
+ "token": "string.other.link"
+ }
+ ],
+ "encodedTokensColors": []
+}
diff --git a/vue-devtools/packages/app-frontend/src/assets/github-theme/light.json b/vue-devtools/packages/app-frontend/src/assets/github-theme/light.json
new file mode 100644
index 0000000000000000000000000000000000000000..42da7a39b0ab52f43fe7545cf054cd6eac37a0dc
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/assets/github-theme/light.json
@@ -0,0 +1,531 @@
+{
+ "inherit": true,
+ "base": "vs",
+ "colors": {
+ "focusBorder": "#0366d6",
+ "foreground": "#24292e",
+ "descriptionForeground": "#6a737d",
+ "errorForeground": "#cb2431",
+ "textLink.foreground": "#0366d6",
+ "textLink.activeForeground": "#0366d6",
+ "textBlockQuote.background": "#f6f8fa",
+ "textBlockQuote.border": "#dfe2e5",
+ "textCodeBlock.background": "#1b1f230d",
+ "textPreformat.foreground": "#586069",
+ "textSeparator.foreground": "#eaecef",
+ "button.background": "#2ea44f",
+ "button.foreground": "#ffffff",
+ "button.hoverBackground": "#2c974b",
+ "button.secondaryBackground": "#eaecef",
+ "button.secondaryForeground": "#24292e",
+ "button.secondaryHoverBackground": "#f3f4f6",
+ "checkbox.background": "#f6f8fa",
+ "checkbox.border": "#e1e4e8",
+ "dropdown.background": "#ffffff",
+ "dropdown.border": "#e1e4e8",
+ "dropdown.foreground": "#24292e",
+ "dropdown.listBackground": "#ffffff",
+ "input.background": "#ffffff",
+ "input.border": "#e1e4e8",
+ "input.foreground": "#24292e",
+ "input.placeholderForeground": "#6a737d",
+ "badge.foreground": "#005cc5",
+ "badge.background": "#dbedff",
+ "progressBar.background": "#2188ff",
+ "titleBar.activeForeground": "#586069",
+ "titleBar.activeBackground": "#ffffff",
+ "titleBar.inactiveForeground": "#6a737d",
+ "titleBar.inactiveBackground": "#f6f8fa",
+ "titleBar.border": "#e1e4e8",
+ "activityBar.foreground": "#24292e",
+ "activityBar.inactiveForeground": "#6a737d",
+ "activityBar.background": "#ffffff",
+ "activityBarBadge.foreground": "#ffffff",
+ "activityBarBadge.background": "#2188ff",
+ "activityBar.activeBorder": "#f9826c",
+ "activityBar.border": "#e1e4e8",
+ "sideBar.foreground": "#24292e",
+ "sideBar.background": "#f6f8fa",
+ "sideBar.border": "#e1e4e8",
+ "sideBarTitle.foreground": "#24292e",
+ "sideBarSectionHeader.foreground": "#24292e",
+ "sideBarSectionHeader.background": "#f6f8fa",
+ "sideBarSectionHeader.border": "#e1e4e8",
+ "list.hoverForeground": "#24292e",
+ "list.inactiveSelectionForeground": "#24292e",
+ "list.activeSelectionForeground": "#24292e",
+ "list.hoverBackground": "#ebf0f4",
+ "list.inactiveSelectionBackground": "#e8eaed",
+ "list.activeSelectionBackground": "#e2e5e9",
+ "list.focusForeground": "#05264c",
+ "list.focusBackground": "#cce5ff",
+ "list.inactiveFocusBackground": "#dbedff",
+ "list.highlightForeground": "#0366d6",
+ "tree.indentGuidesStroke": "#eaecef",
+ "notificationCenterHeader.foreground": "#6a737d",
+ "notificationCenterHeader.background": "#e1e4e8",
+ "notifications.foreground": "#586069",
+ "notifications.background": "#fafbfc",
+ "notifications.border": "#e1e4e8",
+ "notificationsErrorIcon.foreground": "#d73a49",
+ "notificationsWarningIcon.foreground": "#e36209",
+ "notificationsInfoIcon.foreground": "#005cc5",
+ "pickerGroup.border": "#e1e4e8",
+ "pickerGroup.foreground": "#586069",
+ "quickInput.background": "#fafbfc",
+ "quickInput.foreground": "#24292e",
+ "statusBar.foreground": "#586069",
+ "statusBar.background": "#ffffff",
+ "statusBar.border": "#e1e4e8",
+ "statusBar.noFolderBackground": "#ffffff",
+ "statusBar.debuggingBackground": "#d73a49",
+ "statusBar.debuggingForeground": "#ffffff",
+ "statusBarItem.prominentBackground": "#f6f8fa",
+ "editorGroupHeader.tabsBackground": "#f6f8fa",
+ "editorGroupHeader.tabsBorder": "#e1e4e8",
+ "editorGroup.border": "#e1e4e8",
+ "tab.activeForeground": "#24292e",
+ "tab.inactiveForeground": "#6a737d",
+ "tab.inactiveBackground": "#f6f8fa",
+ "tab.activeBackground": "#ffffff",
+ "tab.hoverBackground": "#ffffff",
+ "tab.unfocusedHoverBackground": "#f6f8fa",
+ "tab.border": "#e1e4e8",
+ "tab.unfocusedActiveBorderTop": "#e1e4e8",
+ "tab.activeBorder": "#ffffff",
+ "tab.unfocusedActiveBorder": "#ffffff",
+ "tab.activeBorderTop": "#f9826c",
+ "breadcrumb.foreground": "#6a737d",
+ "breadcrumb.focusForeground": "#24292e",
+ "breadcrumb.activeSelectionForeground": "#586069",
+ "breadcrumbPicker.background": "#ffffff",
+ "editor.foreground": "#24292e",
+ "editor.background": "#ffffff",
+ "editorWidget.background": "#ffffff",
+ "editor.foldBackground": "#959da51a",
+ "editor.lineHighlightBackground": "#fafbfc",
+ "editorLineNumber.foreground": "#959da5",
+ "editorLineNumber.activeForeground": "#24292e",
+ "editorIndentGuide.background": "#eaecef",
+ "editorIndentGuide.activeBackground": "#e1e4e8",
+ "editorWhitespace.foreground": "#d1d5da",
+ "editorCursor.foreground": "#044289",
+ "editor.findMatchBackground": "#ffdf5d",
+ "editor.findMatchHighlightBackground": "#ffdf5d66",
+ "editor.linkedEditingBackground": "#0366d611",
+ "editor.inactiveSelectionBackground": "#0366d611",
+ "editor.selectionBackground": "#0366d625",
+ "editor.selectionHighlightBackground": "#34d05840",
+ "editor.selectionHighlightBorder": "#34d05800",
+ "editor.wordHighlightBackground": "#34d05800",
+ "editor.wordHighlightStrongBackground": "#34d05800",
+ "editor.wordHighlightBorder": "#24943e99",
+ "editor.wordHighlightStrongBorder": "#24943e50",
+ "editorBracketMatch.background": "#34d05840",
+ "editorBracketMatch.border": "#34d05800",
+ "editorGutter.modifiedBackground": "#f9c513",
+ "editorGutter.addedBackground": "#34d058",
+ "editorGutter.deletedBackground": "#d73a49",
+ "diffEditor.insertedTextBackground": "#85e89d33",
+ "diffEditor.removedTextBackground": "#f9758326",
+ "scrollbar.shadow": "#6a737d33",
+ "scrollbarSlider.background": "#959da533",
+ "scrollbarSlider.hoverBackground": "#959da544",
+ "scrollbarSlider.activeBackground": "#959da588",
+ "editorOverviewRuler.border": "#ffffff",
+ "panel.background": "#f6f8fa",
+ "panel.border": "#e1e4e8",
+ "panelTitle.activeBorder": "#f9826c",
+ "panelTitle.activeForeground": "#24292e",
+ "panelTitle.inactiveForeground": "#6a737d",
+ "panelInput.border": "#e1e4e8",
+ "terminal.foreground": "#586069",
+ "terminal.ansiBlack": "#24292e",
+ "terminal.ansiRed": "#d73a49",
+ "terminal.ansiGreen": "#22863a",
+ "terminal.ansiYellow": "#b08800",
+ "terminal.ansiBlue": "#0366d6",
+ "terminal.ansiMagenta": "#6f42c1",
+ "terminal.ansiCyan": "#1b7c83",
+ "terminal.ansiWhite": "#6a737d",
+ "terminal.ansiBrightBlack": "#586069",
+ "terminal.ansiBrightRed": "#cb2431",
+ "terminal.ansiBrightGreen": "#28a745",
+ "terminal.ansiBrightYellow": "#dbab09",
+ "terminal.ansiBrightBlue": "#2188ff",
+ "terminal.ansiBrightMagenta": "#8a63d2",
+ "terminal.ansiBrightCyan": "#3192aa",
+ "terminal.ansiBrightWhite": "#959da5",
+ "gitDecoration.addedResourceForeground": "#22863a",
+ "gitDecoration.modifiedResourceForeground": "#b08800",
+ "gitDecoration.deletedResourceForeground": "#cb2431",
+ "gitDecoration.untrackedResourceForeground": "#22863a",
+ "gitDecoration.ignoredResourceForeground": "#959da5",
+ "gitDecoration.conflictingResourceForeground": "#b08800",
+ "gitDecoration.submoduleResourceForeground": "#586069",
+ "debugToolBar.background": "#ffffff",
+ "editor.stackFrameHighlightBackground": "#ffd33d33",
+ "editor.focusedStackFrameHighlightBackground": "#28a74525",
+ "settings.headerForeground": "#586069",
+ "settings.modifiedItemIndicator": "#f9c513",
+ "welcomePage.buttonBackground": "#fafbfc",
+ "welcomePage.buttonHoverBackground": "#f3f4f6"
+ },
+ "rules": [
+ {
+ "foreground": "#6a737d",
+ "token": "comment"
+ },
+ {
+ "foreground": "#6a737d",
+ "token": "punctuation.definition.comment"
+ },
+ {
+ "foreground": "#6a737d",
+ "token": "string.comment"
+ },
+ {
+ "foreground": "#005cc5",
+ "token": "constant"
+ },
+ {
+ "foreground": "#005cc5",
+ "token": "entity.name.constant"
+ },
+ {
+ "foreground": "#005cc5",
+ "token": "variable.other.constant"
+ },
+ {
+ "foreground": "#005cc5",
+ "token": "variable.language"
+ },
+ {
+ "foreground": "#005cc5",
+ "token": "entity"
+ },
+ {
+ "foreground": "#e36209",
+ "token": "entity.name"
+ },
+ {
+ "foreground": "#e36209",
+ "token": "meta.export.default"
+ },
+ {
+ "foreground": "#e36209",
+ "token": "meta.definition.variable"
+ },
+ {
+ "foreground": "#24292e",
+ "token": "variable.parameter.function"
+ },
+ {
+ "foreground": "#24292e",
+ "token": "meta.jsx.children"
+ },
+ {
+ "foreground": "#24292e",
+ "token": "meta.block"
+ },
+ {
+ "foreground": "#24292e",
+ "token": "meta.tag.attributes"
+ },
+ {
+ "foreground": "#24292e",
+ "token": "entity.name.constant"
+ },
+ {
+ "foreground": "#24292e",
+ "token": "meta.object.member"
+ },
+ {
+ "foreground": "#24292e",
+ "token": "meta.embedded.expression"
+ },
+ {
+ "foreground": "#6f42c1",
+ "token": "entity.name.function"
+ },
+ {
+ "foreground": "#22863a",
+ "token": "entity.name.tag"
+ },
+ {
+ "foreground": "#22863a",
+ "token": "support.class.component"
+ },
+ {
+ "foreground": "#d73a49",
+ "token": "keyword"
+ },
+ {
+ "foreground": "#d73a49",
+ "token": "storage"
+ },
+ {
+ "foreground": "#d73a49",
+ "token": "storage.type"
+ },
+ {
+ "foreground": "#24292e",
+ "token": "storage.modifier.package"
+ },
+ {
+ "foreground": "#24292e",
+ "token": "storage.modifier.import"
+ },
+ {
+ "foreground": "#24292e",
+ "token": "storage.type.java"
+ },
+ {
+ "foreground": "#032f62",
+ "token": "string"
+ },
+ {
+ "foreground": "#032f62",
+ "token": "punctuation.definition.string"
+ },
+ {
+ "foreground": "#032f62",
+ "token": "string punctuation.section.embedded source"
+ },
+ {
+ "foreground": "#005cc5",
+ "token": "support"
+ },
+ {
+ "foreground": "#005cc5",
+ "token": "meta.property-name"
+ },
+ {
+ "foreground": "#e36209",
+ "token": "variable"
+ },
+ {
+ "foreground": "#24292e",
+ "token": "variable.other"
+ },
+ {
+ "fontStyle": "italic",
+ "foreground": "#b31d28",
+ "token": "invalid.broken"
+ },
+ {
+ "fontStyle": "italic",
+ "foreground": "#b31d28",
+ "token": "invalid.deprecated"
+ },
+ {
+ "fontStyle": "italic",
+ "foreground": "#b31d28",
+ "token": "invalid.illegal"
+ },
+ {
+ "fontStyle": "italic",
+ "foreground": "#b31d28",
+ "token": "invalid.unimplemented"
+ },
+ {
+ "fontStyle": "italic underline",
+ "background": "#d73a49",
+ "foreground": "#fafbfc",
+ "content": "^M",
+ "token": "carriage-return"
+ },
+ {
+ "foreground": "#b31d28",
+ "token": "message.error"
+ },
+ {
+ "foreground": "#24292e",
+ "token": "string source"
+ },
+ {
+ "foreground": "#005cc5",
+ "token": "string variable"
+ },
+ {
+ "foreground": "#032f62",
+ "token": "source.regexp"
+ },
+ {
+ "foreground": "#032f62",
+ "token": "string.regexp"
+ },
+ {
+ "foreground": "#032f62",
+ "token": "string.regexp.character-class"
+ },
+ {
+ "foreground": "#032f62",
+ "token": "string.regexp constant.character.escape"
+ },
+ {
+ "foreground": "#032f62",
+ "token": "string.regexp source.ruby.embedded"
+ },
+ {
+ "foreground": "#032f62",
+ "token": "string.regexp string.regexp.arbitrary-repitition"
+ },
+ {
+ "fontStyle": "bold",
+ "foreground": "#22863a",
+ "token": "string.regexp constant.character.escape"
+ },
+ {
+ "foreground": "#005cc5",
+ "token": "support.constant"
+ },
+ {
+ "foreground": "#005cc5",
+ "token": "support.variable"
+ },
+ {
+ "foreground": "#005cc5",
+ "token": "meta.module-reference"
+ },
+ {
+ "foreground": "#e36209",
+ "token": "punctuation.definition.list.begin.markdown"
+ },
+ {
+ "fontStyle": "bold",
+ "foreground": "#005cc5",
+ "token": "markup.heading"
+ },
+ {
+ "fontStyle": "bold",
+ "foreground": "#005cc5",
+ "token": "markup.heading entity.name"
+ },
+ {
+ "foreground": "#22863a",
+ "token": "markup.quote"
+ },
+ {
+ "fontStyle": "italic",
+ "foreground": "#24292e",
+ "token": "markup.italic"
+ },
+ {
+ "fontStyle": "bold",
+ "foreground": "#24292e",
+ "token": "markup.bold"
+ },
+ {
+ "foreground": "#005cc5",
+ "token": "markup.raw"
+ },
+ {
+ "background": "#ffeef0",
+ "foreground": "#b31d28",
+ "token": "markup.deleted"
+ },
+ {
+ "background": "#ffeef0",
+ "foreground": "#b31d28",
+ "token": "meta.diff.header.from-file"
+ },
+ {
+ "background": "#ffeef0",
+ "foreground": "#b31d28",
+ "token": "punctuation.definition.deleted"
+ },
+ {
+ "background": "#f0fff4",
+ "foreground": "#22863a",
+ "token": "markup.inserted"
+ },
+ {
+ "background": "#f0fff4",
+ "foreground": "#22863a",
+ "token": "meta.diff.header.to-file"
+ },
+ {
+ "background": "#f0fff4",
+ "foreground": "#22863a",
+ "token": "punctuation.definition.inserted"
+ },
+ {
+ "background": "#ffebda",
+ "foreground": "#e36209",
+ "token": "markup.changed"
+ },
+ {
+ "background": "#ffebda",
+ "foreground": "#e36209",
+ "token": "punctuation.definition.changed"
+ },
+ {
+ "foreground": "#f6f8fa",
+ "background": "#005cc5",
+ "token": "markup.ignored"
+ },
+ {
+ "foreground": "#f6f8fa",
+ "background": "#005cc5",
+ "token": "markup.untracked"
+ },
+ {
+ "foreground": "#6f42c1",
+ "fontStyle": "bold",
+ "token": "meta.diff.range"
+ },
+ {
+ "foreground": "#005cc5",
+ "token": "meta.diff.header"
+ },
+ {
+ "fontStyle": "bold",
+ "foreground": "#005cc5",
+ "token": "meta.separator"
+ },
+ {
+ "foreground": "#005cc5",
+ "token": "meta.output"
+ },
+ {
+ "foreground": "#586069",
+ "token": "brackethighlighter.tag"
+ },
+ {
+ "foreground": "#586069",
+ "token": "brackethighlighter.curly"
+ },
+ {
+ "foreground": "#586069",
+ "token": "brackethighlighter.round"
+ },
+ {
+ "foreground": "#586069",
+ "token": "brackethighlighter.square"
+ },
+ {
+ "foreground": "#586069",
+ "token": "brackethighlighter.angle"
+ },
+ {
+ "foreground": "#586069",
+ "token": "brackethighlighter.quote"
+ },
+ {
+ "foreground": "#b31d28",
+ "token": "brackethighlighter.unmatched"
+ },
+ {
+ "foreground": "#032f62",
+ "fontStyle": "underline",
+ "token": "constant.other.reference.link"
+ },
+ {
+ "foreground": "#032f62",
+ "fontStyle": "underline",
+ "token": "string.other.link"
+ }
+ ],
+ "encodedTokensColors": []
+}
diff --git a/vue-devtools/packages/app-frontend/src/assets/style/imports.styl b/vue-devtools/packages/app-frontend/src/assets/style/imports.styl
new file mode 100644
index 0000000000000000000000000000000000000000..095a1c8bd9fe0a16c0b70fd2866b908f07e1beb8
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/assets/style/imports.styl
@@ -0,0 +1,2 @@
+@import '~@vue/ui/src/style/imports'
+@import 'variables'
diff --git a/vue-devtools/packages/app-frontend/src/assets/style/index.postcss b/vue-devtools/packages/app-frontend/src/assets/style/index.postcss
new file mode 100644
index 0000000000000000000000000000000000000000..3d71cf5bb3de3550e4e9b87923271dcc1a62668d
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/assets/style/index.postcss
@@ -0,0 +1,126 @@
+html, body, #app {
+ @apply dark:!bg-gray-800;
+}
+
+.vue-ui-high-contrast {
+ #app {
+ @apply !bg-black;
+ }
+}
+
+/* Poppers */
+
+.v-popper__popper.v-popper--theme-tooltip code {
+ @apply bg-gray-500/50 rounded px-1 text-[11px] font-mono;
+}
+
+.v-popper--theme-dropdown {
+ .vue-ui-dark-mode & {
+ .v-popper__inner,
+ .v-popper__arrow-outer {
+ @apply border-gray-900;
+ }
+
+ .v-popper__inner {
+ @apply bg-gray-800;
+ }
+
+ .v-popper__arrow-inner {
+ @apply border-gray-800;
+ }
+ }
+}
+
+/* Scrollbars */
+
+::-webkit-scrollbar {
+ width: 10px;
+ height: 10px;
+}
+
+::-webkit-scrollbar-track-piece {
+ @apply bg-transparent;
+}
+
+::-webkit-scrollbar-track:hover {
+ @apply bg-gray-600/5 dark:bg-gray-600/10;
+}
+
+::-webkit-scrollbar-thumb {
+ @apply bg-gray-300 hover:bg-gray-600 border-[3px] border-transparent bg-clip-padding rounded dark:bg-gray-700 dark:hover:bg-gray-500;
+}
+
+.vue-ui-dark-mode {
+ scrollbar-color: theme('colors.gray.800') theme('colors.black');
+
+ .selectable-item {
+ @apply bg-gray-800 hover:bg-gray-900;
+
+ &.selected {
+ @apply hover:bg-green-600;
+ }
+ }
+}
+
+/* Buttons */
+
+.vue-ui-button:not(.flat):not(.vue-ui-dropdown-button):not(.primary):not(.secondary):not(.danger) {
+ @apply dark:bg-gray-700 dark:hover:!bg-gray-600;
+}
+
+.vue-ui-button.flat,
+.vue-ui-dropdown-button {
+ @apply hover:!bg-green-500/30;
+}
+
+.vue-ui-dark-mode {
+ .vue-ui-group {
+ .vue-ui-button:not(.flat) {
+ @apply !bg-gray-700 hover:!bg-gray-600;
+
+ &.selected {
+ @apply !bg-green-700;
+ }
+ }
+ }
+}
+
+/* Switch */
+
+.vue-ui-dark-mode {
+ .vue-ui-switch {
+ > .content > .wrapper {
+ @apply bg-gray-700;
+ }
+ &.selected {
+ > .content > .wrapper {
+ @apply bg-green-600;
+ }
+ }
+ }
+}
+
+/* Tab */
+
+.vue-ui-dark-mode {
+ .vue-ui-group {
+ .indicator .content {
+ @apply !border-b-green-500;
+ }
+ .vue-ui-button.selected {
+ @apply text-green-500;
+ }
+ }
+}
+
+/* Arrows */
+
+.arrow {
+ @apply inline-block w-0 h-0 transition-transform duration-150 ease-out text-gray-500;
+
+ &.right {
+ border-top: 4px solid transparent;
+ border-bottom: 4px solid transparent;
+ border-left: 6px solid currentColor;
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/assets/style/index.styl b/vue-devtools/packages/app-frontend/src/assets/style/index.styl
new file mode 100644
index 0000000000000000000000000000000000000000..98183d731a78734a8ba2c54794d1f44740fc5a2e
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/assets/style/index.styl
@@ -0,0 +1,114 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@import '~@vue/ui/dist/vue-ui.css'
+
+@import 'imports'
+@import 'transitions'
+
+@font-face
+ font-family 'Roboto'
+ font-style normal
+ font-weight 400
+ src local('Roboto'), local('Roboto-Regular'), url(../Roboto-Regular.woff2) format('woff2')
+
+@font-face
+ font-family 'Roboto Mono'
+ font-style normal
+ font-weight 400
+ src local('Roboto Mono'), local('Roboto-Mono'), url(../Roboto-Mono.ttf) format('truetype')
+
+html, body
+ margin 0
+ padding 0
+ font-family Roboto
+ font-size 16px
+ color #444
+ height 100%
+
+body
+ overflow hidden
+
+#app
+ width: 100%
+ height: 100%
+
+button:focus
+ outline none
+
+.selectable-item
+ background-color $background-color
+ &:hover
+ background-color $hover-color
+ &.selected,
+ &.active
+ background-color $active-color
+ color #fff
+ .item-name,
+ .arrow
+ color #fff
+
+ .vue-ui-dark-mode &
+ background-color $dark-background-color
+ &:hover
+ background-color $dark-hover-color
+ .arrow
+ color theme('colors.gray.600')
+ &.selected,
+ &.active
+ color #fff
+ background-color $active-color
+
+.vue-ui-icon svg
+ fill currentColor
+
+// Tooltips
+
+.keyboard
+ display inline-block
+ min-width 22px
+ text-align center
+ background rgba($grey, .3)
+ padding 2px 4px 0
+ border-radius 3px
+ margin-bottom 6px
+ box-shadow 0 3px 0 rgba($grey, .2)
+ .vue-ui-dark-mode &
+ background rgba($grey, .9)
+ box-shadow 0 3px 0 rgba($grey, .6)
+
+.mono
+ font-family Menlo, Consolas, monospace
+
+.v-popper__popper.v-popper--theme-tooltip
+ pointer-events none
+ font-size 12px
+
+ .vue-ui-icon
+ width 16px
+ height @width
+ vertical-align middle
+
+.vue-ui-dark-mode .v-popper__popper.v-popper--theme-tooltip .vue-ui-icon svg
+ fill #666
+
+.v-popper__popper.v-popper--theme-dropdown .v-popper__inner
+ max-height calc(100vh - 32px - 8px - 4px)
+ overflow-y auto
+
+.scroll-smooth
+ scroll-behavior smooth
+
+.grayscale
+ filter grayscale(1)
+
+.right-icon-reveal:not(:hover)
+ .vue-ui-icon.right
+ opacity 0
+
+.v-popper--theme-tooltip
+ .vue-ui-dark-mode &
+ .v-popper__arrow-inner,
+ .v-popper__arrow-outer
+ border-color $vue-ui-white
diff --git a/vue-devtools/packages/app-frontend/src/assets/style/transitions.styl b/vue-devtools/packages/app-frontend/src/assets/style/transitions.styl
new file mode 100644
index 0000000000000000000000000000000000000000..f835550e6f6713c6c7a626d5e9c8b0e66ec5b3ff
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/assets/style/transitions.styl
@@ -0,0 +1,25 @@
+.slide-up-enter
+ opacity 0
+ transform translate(0, 50%)
+
+.slide-up-leave-to
+ opacity 0
+ transform translate(0, -50%)
+
+.slide-down-enter, .slide-down-leave-to
+ opacity 0
+ transform translate(0, -20px)
+
+@keyframes rotate
+ 0%
+ transform rotate(0deg)
+ 100%
+ transform rotate(360deg)
+
+@keyframes pulse
+ 0%
+ opacity 1
+ 50%
+ opacity .2
+ 100%
+ opacity 1
diff --git a/vue-devtools/packages/app-frontend/src/assets/style/variables.styl b/vue-devtools/packages/app-frontend/src/assets/style/variables.styl
new file mode 100644
index 0000000000000000000000000000000000000000..51eab2e8e288fca44c5f2c754f3122546ec2dcd8
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/assets/style/variables.styl
@@ -0,0 +1,80 @@
+// Colors
+$blue = #44A1FF
+$grey = #DDDDDD
+$darkGrey = #CCC
+$darkerGrey = #AAA
+$blueishGrey = #486887
+$green = #42B983
+$darkerGreen = #3BA776
+$slate = #242424
+$white = #FFFFFF
+$orange = #FF6B00
+$red = #c41a16
+$black = #222
+$vividBlue = #0033cc
+$purple = #997fff
+$pink = #881391
+$lightPink = #e36eec
+
+// The min-width to give icons text...
+$wide = 1100px
+
+// The min-height to give the tools a little more breathing room...
+$tall = 350px
+
+// Theme
+$active-color = $darkerGreen
+$border-color = $md-grey-200
+$background-color = $white
+$component-color = $active-color
+$hover-color = #c2e9d7
+
+$dark-active-color = $active-color
+$dark-border-color = darken($vue-ui-gray-900, 30%)
+$dark-background-color = $vue-ui-black
+$dark-component-color = $active-color
+$dark-hover-color = $vue-ui-color-dark
+
+// Entries
+// TODO: FIX THIS
+// .no-entries
+// color: #ccc
+// text-align: center
+// margin-top: 50px
+// line-height: 30px
+//
+// .entry
+// position: relative;
+// font-family Menlo, Consolas, monospace
+// color #881391
+// cursor pointer
+// padding 10px 20px
+// font-size 12px
+// background-color $background-color
+// box-shadow 0 1px 5px rgba(0,0,0,.12)
+// .entry-name
+// font-weight 600
+// .entry-source
+// color #999
+// .component-name
+// color $component-color
+// .entry-type
+// color #999
+// margin-left 8px
+// &.active
+// color #fff
+// background-color $active-color
+// .time, .entry-type, .component-name
+// color lighten($active-color, 75%)
+// .entry-name
+// color: #fff
+// .entry-source
+// color #ddd
+// .app.dark &
+// background-color $dark-background-color
+//
+// .time
+// font-size 11px
+// color #999
+// float right
+// margin-top 3px
diff --git a/vue-devtools/packages/app-frontend/src/assets/undraw_Gift_box.svg b/vue-devtools/packages/app-frontend/src/assets/undraw_Gift_box.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e65cf5ca6e9ee38df455100b43e1a95114c04bbb
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/assets/undraw_Gift_box.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vue-devtools/packages/app-frontend/src/assets/vue-logo-beta.svg b/vue-devtools/packages/app-frontend/src/assets/vue-logo-beta.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c1dc6494782575925f437f36e2a79656848ed468
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/assets/vue-logo-beta.svg
@@ -0,0 +1,88 @@
+
+
+
+
\ No newline at end of file
diff --git a/vue-devtools/packages/app-frontend/src/assets/vue-logo.svg b/vue-devtools/packages/app-frontend/src/assets/vue-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..932a122a38f90527d5919504f3a24444cda8f91b
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/assets/vue-logo.svg
@@ -0,0 +1,61 @@
+
+
+
+
\ No newline at end of file
diff --git a/vue-devtools/packages/app-frontend/src/assets/welcome/app-selector.png b/vue-devtools/packages/app-frontend/src/assets/welcome/app-selector.png
new file mode 100644
index 0000000000000000000000000000000000000000..530b597e18e715a24f660e011bdad95ed9198f50
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/welcome/app-selector.png differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/welcome/components-menu.png b/vue-devtools/packages/app-frontend/src/assets/welcome/components-menu.png
new file mode 100644
index 0000000000000000000000000000000000000000..0ee40a1eeb88b6acb8e1f560596d010c2010e2b6
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/welcome/components-menu.png differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/welcome/components-pinia.png b/vue-devtools/packages/app-frontend/src/assets/welcome/components-pinia.png
new file mode 100644
index 0000000000000000000000000000000000000000..98bf1b24ae4f0c0636ba450f14330fc0ab3f545e
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/welcome/components-pinia.png differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/welcome/components.png b/vue-devtools/packages/app-frontend/src/assets/welcome/components.png
new file mode 100644
index 0000000000000000000000000000000000000000..9544e6a13f6f4193f352bbcaef6b7275c46985cd
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/welcome/components.png differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/welcome/inspector-pinia.png b/vue-devtools/packages/app-frontend/src/assets/welcome/inspector-pinia.png
new file mode 100644
index 0000000000000000000000000000000000000000..b99ec083e578dfda2d8503a40db9c9467d3db21e
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/welcome/inspector-pinia.png differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/welcome/inspector-pinia2.png b/vue-devtools/packages/app-frontend/src/assets/welcome/inspector-pinia2.png
new file mode 100644
index 0000000000000000000000000000000000000000..3e15cae4bbd95c0235588536cadc6e8a6fdfc367
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/welcome/inspector-pinia2.png differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/welcome/main-tabs.png b/vue-devtools/packages/app-frontend/src/assets/welcome/main-tabs.png
new file mode 100644
index 0000000000000000000000000000000000000000..b9b744a90b8404070928456663173e3802c719f1
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/welcome/main-tabs.png differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/welcome/settings-pinia.png b/vue-devtools/packages/app-frontend/src/assets/welcome/settings-pinia.png
new file mode 100644
index 0000000000000000000000000000000000000000..9445012e7d939dfa3e04c6779d2f8bd459595976
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/welcome/settings-pinia.png differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/welcome/timeline-perf.png b/vue-devtools/packages/app-frontend/src/assets/welcome/timeline-perf.png
new file mode 100644
index 0000000000000000000000000000000000000000..756346e946aaa6a1153458aadb8038c0f5d71a1e
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/welcome/timeline-perf.png differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/welcome/timeline-perf2.png b/vue-devtools/packages/app-frontend/src/assets/welcome/timeline-perf2.png
new file mode 100644
index 0000000000000000000000000000000000000000..c1daf0a7a4a07fd732e64c14be0b26a17fd42bb7
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/welcome/timeline-perf2.png differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/welcome/timeline-pinia.png b/vue-devtools/packages/app-frontend/src/assets/welcome/timeline-pinia.png
new file mode 100644
index 0000000000000000000000000000000000000000..aa0ad41312359bd83020ab0b59da9a287739d567
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/welcome/timeline-pinia.png differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/welcome/timeline-router.png b/vue-devtools/packages/app-frontend/src/assets/welcome/timeline-router.png
new file mode 100644
index 0000000000000000000000000000000000000000..47b7a6c537d541beaecea4623f4e6a55f8e71418
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/welcome/timeline-router.png differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/welcome/timeline.png b/vue-devtools/packages/app-frontend/src/assets/welcome/timeline.png
new file mode 100644
index 0000000000000000000000000000000000000000..27c52d70b611eb94c84f632f84305b607f81ea54
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/welcome/timeline.png differ
diff --git a/vue-devtools/packages/app-frontend/src/assets/welcome/version-check.png b/vue-devtools/packages/app-frontend/src/assets/welcome/version-check.png
new file mode 100644
index 0000000000000000000000000000000000000000..2b33ae6535b42b9e0308d31aa9e5f8230bf61a0f
Binary files /dev/null and b/vue-devtools/packages/app-frontend/src/assets/welcome/version-check.png differ
diff --git a/vue-devtools/packages/app-frontend/src/features/App.vue b/vue-devtools/packages/app-frontend/src/features/App.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f091b9bf1eb01b281200773c78ec0743e06fd55f
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/App.vue
@@ -0,0 +1,145 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/apps/AppSelect.vue b/vue-devtools/packages/app-frontend/src/features/apps/AppSelect.vue
new file mode 100644
index 0000000000000000000000000000000000000000..aff512c7ffa27c028db8f6ffaa30722e22bcc978
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/apps/AppSelect.vue
@@ -0,0 +1,126 @@
+
+
+
+ selectApp(app.id)"
+ >
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+ Scan apps
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/apps/AppSelectItem.vue b/vue-devtools/packages/app-frontend/src/features/apps/AppSelectItem.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0e378f55c35f387b5850cb955eaccd0cf457aa7b
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/apps/AppSelectItem.vue
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+ {{ app.iframe }}
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/apps/AppSelectPane.vue b/vue-devtools/packages/app-frontend/src/features/apps/AppSelectPane.vue
new file mode 100644
index 0000000000000000000000000000000000000000..9b34c6deebe8b0c0ec763209c16ac53cfc26ee03
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/apps/AppSelectPane.vue
@@ -0,0 +1,112 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/apps/AppSelectPaneItem.vue b/vue-devtools/packages/app-frontend/src/features/apps/AppSelectPaneItem.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f52f0adf0e409ca669934bb3eb7b80030a0a3e08
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/apps/AppSelectPaneItem.vue
@@ -0,0 +1,101 @@
+
+
+
+
+
+
{{ app.name }}
+
+
+ {{ app.version }}
+
+
+
+
+
+
+
+ {{ app.id }}
+
+
+
+
+
+ {{ app.iframe }}
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/apps/index.ts b/vue-devtools/packages/app-frontend/src/features/apps/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1dd5d99aeaf4255177cc9627ecb2ed339411a290
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/apps/index.ts
@@ -0,0 +1,118 @@
+import { computed, ref } from 'vue'
+import type { Bridge } from '@vue-devtools/shared-utils'
+import { BridgeEvents } from '@vue-devtools/shared-utils'
+import { getBridge } from '@front/features/bridge'
+import { useRoute, useRouter } from 'vue-router'
+import { fetchLayers } from '../timeline/composable'
+
+export interface AppRecord {
+ id: string
+ name: string
+ version: string
+ iframe: string
+}
+
+const apps = ref([])
+
+export function useCurrentApp() {
+ const route = useRoute()
+ const currentAppId = computed(() => route.params.appId as string)
+ const currentApp = computed(() => apps.value.find(a => currentAppId.value === a.id))
+
+ return {
+ currentAppId,
+ currentApp,
+ }
+}
+
+export function useApps() {
+ const router = useRouter()
+
+ const {
+ currentAppId,
+ currentApp,
+ } = useCurrentApp()
+
+ function selectApp(id: string) {
+ if (currentAppId.value !== id) {
+ router.push({
+ params: {
+ appId: id.toString(),
+ componentId: null,
+ },
+ })
+ }
+ }
+
+ return {
+ apps,
+ currentAppId,
+ currentApp,
+ selectApp,
+ }
+}
+
+function addApp(app: AppRecord) {
+ removeApp(app.id)
+ apps.value.push(app)
+}
+
+function removeApp(appId: string) {
+ const index = apps.value.findIndex(app => app.id === appId)
+ if (index !== -1) {
+ apps.value.splice(index, 1)
+ }
+}
+
+export function getApps() {
+ return apps.value
+}
+
+function fetchApps() {
+ getBridge().send(BridgeEvents.TO_BACK_APP_LIST, {})
+}
+
+export const pendingSelectAppId = ref(null)
+
+const pendingSelectPromises: (() => void)[] = []
+
+export function waitForAppSelect(): Promise {
+ if (!pendingSelectAppId.value) {
+ return Promise.resolve()
+ }
+ else {
+ return new Promise((resolve) => {
+ pendingSelectPromises.push(resolve)
+ })
+ }
+}
+
+export function scanLegacyApps() {
+ getBridge().send(BridgeEvents.TO_BACK_SCAN_LEGACY_APPS, {})
+}
+
+export function setupAppsBridgeEvents(bridge: Bridge) {
+ bridge.on(BridgeEvents.TO_FRONT_APP_ADD, ({ appRecord }) => {
+ addApp(appRecord)
+ fetchLayers()
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_APP_REMOVE, ({ id }) => {
+ removeApp(id)
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_APP_LIST, ({ apps: list }) => {
+ apps.value = list
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_APP_SELECTED, ({ id }) => {
+ if (pendingSelectAppId.value === id) {
+ pendingSelectAppId.value = null
+ for (const resolve of pendingSelectPromises) {
+ resolve()
+ }
+ }
+ })
+
+ fetchApps()
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/apps/vue-version-check.ts b/vue-devtools/packages/app-frontend/src/features/apps/vue-version-check.ts
new file mode 100644
index 0000000000000000000000000000000000000000..54bd481d6c2f2c5aaeb786a9b2ed4c6046d2c79d
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/apps/vue-version-check.ts
@@ -0,0 +1,17 @@
+import { onMounted, ref } from 'vue'
+import semver from 'semver'
+
+const packageData = ref(null)
+
+export function useVueVersionCheck() {
+ function getLatestVersion(currentVersion: string): string {
+ if (packageData.value && packageData.value.versions) {
+ return semver.maxSatisfying(Object.keys(packageData.value.versions), `^${currentVersion}`)
+ }
+ return currentVersion
+ }
+
+ return {
+ getLatestVersion,
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/bridge/index.ts b/vue-devtools/packages/app-frontend/src/features/bridge/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b0b661457b878f09b14418329052292c20a268d2
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/bridge/index.ts
@@ -0,0 +1,58 @@
+import { onUnmounted } from 'vue'
+import type { Bridge } from '@vue-devtools/shared-utils'
+import { BridgeEvents } from '@vue-devtools/shared-utils'
+
+let bridge: Bridge
+
+interface Sub {
+ type: string
+ key: string
+}
+
+export function useBridge() {
+ const cbs = []
+
+ function onBridge(event: BridgeEvents, cb: (payload: any) => void | Promise) {
+ cbs.push({ event, cb })
+ bridge.on(event, cb)
+ }
+
+ const subs: Sub[] = []
+
+ function subscribe(type: string, key: string) {
+ const sub = { type, key }
+ subs.push(sub)
+ bridge.send(BridgeEvents.TO_BACK_SUBSCRIBE, key)
+ return () => {
+ const index = subs.indexOf(sub)
+ if (index !== -1) {
+ subs.splice(index, 1)
+ }
+ bridge.send(BridgeEvents.TO_BACK_UNSUBSCRIBE, key)
+ }
+ }
+
+ onUnmounted(() => {
+ for (const { event, cb } of cbs) {
+ bridge.off(event, cb)
+ }
+
+ for (const sub of subs) {
+ bridge.send(BridgeEvents.TO_BACK_UNSUBSCRIBE, sub.key)
+ }
+ })
+
+ return {
+ bridge,
+ onBridge,
+ subscribe,
+ }
+}
+
+export function setBridge(b: Bridge) {
+ bridge = b
+}
+
+export function getBridge(): Bridge | null {
+ return bridge
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/chrome/index.ts b/vue-devtools/packages/app-frontend/src/features/chrome/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7d49636b2f211e636ad9dc317ea14d6ed8f20012
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/chrome/index.ts
@@ -0,0 +1 @@
+export * from './pane-visibility'
diff --git a/vue-devtools/packages/app-frontend/src/features/chrome/pane-visibility.ts b/vue-devtools/packages/app-frontend/src/features/chrome/pane-visibility.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3319a72421efd7d1ced76c0d54df188c6a6c4dee
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/chrome/pane-visibility.ts
@@ -0,0 +1,36 @@
+import { isChrome } from '@vue-devtools/shared-utils'
+
+let panelShown = !isChrome
+let pendingAction: (() => void | Promise) | null = null
+
+if (isChrome) {
+ chrome.runtime.onMessage.addListener((request) => {
+ if (request === 'vue-panel-shown') {
+ onPanelShown()
+ }
+ else if (request === 'vue-panel-hidden') {
+ onPanelHidden()
+ }
+ })
+}
+
+export function ensurePaneShown(cb: () => void | Promise) {
+ if (panelShown) {
+ cb()
+ }
+ else {
+ pendingAction = cb
+ }
+}
+
+function onPanelShown() {
+ panelShown = true
+ if (pendingAction) {
+ pendingAction()
+ pendingAction = null
+ }
+}
+
+function onPanelHidden() {
+ panelShown = false
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/code/CodeEditor.vue b/vue-devtools/packages/app-frontend/src/features/code/CodeEditor.vue
new file mode 100644
index 0000000000000000000000000000000000000000..53fd4b047061a14d500be863910e32316e7c4bc3
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/code/CodeEditor.vue
@@ -0,0 +1,168 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/components/ComponentTreeNode.vue b/vue-devtools/packages/app-frontend/src/features/components/ComponentTreeNode.vue
new file mode 100644
index 0000000000000000000000000000000000000000..414ff879289a2558969321e1a5a92f6b1e9623c5
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/components/ComponentTreeNode.vue
@@ -0,0 +1,353 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ <
+
+ {{ displayName }}
+
+
+ key={{ instance.renderKey }}
+
+
+ >
+
+
+
+
+ fragment
+
+
+ inactive
+
+
+ {{ tag.label }}
+
+
+
+ {{ instance.id }}
+
+
+ {{ instance.domOrder }}
+
+
+
+
+
+
+
+
+ Updated {{ updateTrackingTimeAgo }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/components/ComponentsInspector.vue b/vue-devtools/packages/app-frontend/src/features/components/ComponentsInspector.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4b4076056797496976068500d9e02c9c38e58e9c
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/components/ComponentsInspector.vue
@@ -0,0 +1,291 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Component names:
+
+
+
+
+
+
+
+
+
+
+ Performance monitoring
+
+
+ Turn off if your app is slowed down
+
+
+
+
+
+ Update tracking
+
+
+ Turn off if your app is slowed down
+
+
+
+
+
+ Editable props
+
+
+
+ May print warnings in the console
+
+
+
+
+
+ Highlight updates
+
+
+
+ Don't enable if you are sensitive to flashing
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Click on a component on the page to select it
+
+
+
+ Cancel
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/components/RenderCode.vue b/vue-devtools/packages/app-frontend/src/features/components/RenderCode.vue
new file mode 100644
index 0000000000000000000000000000000000000000..52fc9488b3ae5e943bbd3ac3b93ff00c72fcfdf1
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/components/RenderCode.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/components/SelectedComponentPane.vue b/vue-devtools/packages/app-frontend/src/features/components/SelectedComponentPane.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c1e6673d8a6ddac0abfb9b851f78012c4784ce91
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/components/SelectedComponentPane.vue
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+ <
+
+ {{ displayName }}
+
+ >
+
+
+ Copied!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Select a component
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/components/composable/components.ts b/vue-devtools/packages/app-frontend/src/features/components/composable/components.ts
new file mode 100644
index 0000000000000000000000000000000000000000..352df153d9c3eee0145d8946fce22a774000d5d3
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/components/composable/components.ts
@@ -0,0 +1,441 @@
+import type { Ref } from 'vue'
+import { computed, onMounted, ref, watch } from 'vue'
+import type { ComponentTreeNode, EditStatePayload, InspectedComponentData } from '@vue/devtools-api'
+import groupBy from 'lodash/groupBy'
+import {
+ BridgeEvents,
+ BridgeSubscriptions,
+ isChrome,
+ openInEditor,
+ searchDeepInObject,
+ setStorage,
+ sortByKey,
+} from '@vue-devtools/shared-utils'
+import { getBridge, useBridge } from '@front/features/bridge'
+import type { AppRecord } from '@front/features/apps'
+import { useCurrentApp, waitForAppSelect } from '@front/features/apps'
+import { useRoute, useRouter } from 'vue-router'
+
+export const rootInstances = ref([])
+export const componentsMap = ref>({})
+let componentsParent: Record = {}
+const treeFilter = ref('')
+export const selectedComponentId = ref(null)
+export const selectedComponentData = ref(null)
+const selectedComponentStateFilter = ref('')
+export const selectedComponentPendingId = ref(null)
+let lastSelectedApp: AppRecord = null
+export const lastSelectedComponentId: Record = {}
+export const expandedMap = ref>({})
+
+export function useComponentRequests() {
+ const router = useRouter()
+
+ function selectComponent(id: ComponentTreeNode['id'], replace = false) {
+ if (selectedComponentId.value !== id) {
+ router[replace ? 'replace' : 'push']({
+ params: {
+ appId: getAppIdFromComponentId(id),
+ componentId: id,
+ },
+ })
+ }
+ else {
+ loadComponent(id)
+ }
+ }
+
+ return {
+ requestComponentTree,
+ selectComponent,
+ }
+}
+
+export function useComponents() {
+ const { onBridge, subscribe } = useBridge()
+ const route = useRoute()
+ const {
+ requestComponentTree,
+ selectComponent,
+ } = useComponentRequests()
+ const { currentAppId } = useCurrentApp()
+
+ watch(treeFilter, () => {
+ requestComponentTree()
+ })
+
+ watch(() => route.params.componentId, () => {
+ const value = route.params.componentId as string
+ if (value && getAppIdFromComponentId(value) === currentAppId.value) {
+ selectedComponentId.value = value
+ loadComponent(value)
+ }
+ }, {
+ immediate: true,
+ })
+
+ function subscribeToSelectedData() {
+ let unsub
+ watch(selectedComponentId, (value) => {
+ if (unsub) {
+ unsub()
+ unsub = null
+ }
+
+ if (value != null) {
+ unsub = subscribe(BridgeSubscriptions.SELECTED_COMPONENT_DATA, value)
+ }
+ }, {
+ immediate: true,
+ })
+ }
+
+ // We watch for the tree data so that we can auto load the current selected component
+ watch(componentsMap, () => {
+ if (selectedComponentId.value && selectedComponentPendingId.value !== selectedComponentId.value && !selectedComponentData.value) {
+ selectComponent(selectedComponentId.value)
+ }
+ }, {
+ immediate: true,
+ deep: true,
+ })
+
+ onBridge(BridgeEvents.TO_FRONT_APP_SELECTED, async ({ id }) => {
+ await waitForAppSelect()
+ requestComponentTree()
+ selectedComponentData.value = null
+ if (lastSelectedApp !== null) {
+ selectLastComponent()
+ }
+ lastSelectedApp = id
+ })
+
+ // Re-select last selected component when switching back to inspector component tab
+ function selectLastComponent() {
+ const id = lastSelectedComponentId[currentAppId.value]
+ if (id) {
+ selectComponent(id, true)
+ }
+ }
+
+ return {
+ rootInstances: computed(() => rootInstances.value),
+ treeFilter,
+ selectedComponentId: computed(() => selectedComponentId.value),
+ requestComponentTree,
+ selectComponent,
+ selectLastComponent,
+ subscribeToSelectedData,
+ }
+}
+
+export function useComponent(instance: Ref) {
+ const { selectComponent, requestComponentTree } = useComponentRequests()
+ const { subscribe } = useBridge()
+
+ const isExpanded = computed(() => isComponentOpen(instance.value.id))
+ const isExpandedUndefined = computed(() => expandedMap.value[instance.value.id] == null)
+
+ function toggleExpand(recursively = false, value?, child?) {
+ const treeNode = child || instance.value
+ if (!treeNode.hasChildren) {
+ return
+ }
+ const isOpen = value === undefined ? !isExpanded.value : value
+ setComponentOpen(treeNode.id, isOpen)
+ if (isComponentOpen(treeNode.id)) {
+ requestComponentTree(treeNode.id, recursively)
+ }
+ else {
+ // stop expanding all treenode
+ treeNode.autoOpen = false
+ }
+ if (recursively) {
+ treeNode.children.forEach((child) => {
+ toggleExpand(recursively, value, child)
+ })
+ }
+ }
+
+ const isSelected = computed(() => selectedComponentId.value === instance.value.id)
+
+ function select(id = instance.value.id) {
+ selectComponent(id)
+ }
+
+ function subscribeToComponentTree() {
+ let unsub
+ watch(() => instance.value.id, (value) => {
+ if (unsub) {
+ unsub()
+ unsub = null
+ }
+
+ if (value != null) {
+ unsub = subscribe(BridgeSubscriptions.COMPONENT_TREE, value)
+ }
+ }, {
+ immediate: true,
+ })
+ }
+
+ onMounted(() => {
+ if (instance.value.autoOpen) {
+ toggleExpand(true, true)
+ }
+ else if (isExpanded.value) {
+ requestComponentTree(instance.value.id)
+ }
+ })
+
+ return {
+ isExpanded,
+ isExpandedUndefined,
+ isComponentOpen,
+ toggleExpand,
+ isSelected,
+ select,
+ subscribeToComponentTree,
+ }
+}
+
+export function setComponentOpen(id: ComponentTreeNode['id'], isOpen: boolean) {
+ expandedMap.value[id] = isOpen
+}
+
+export function isComponentOpen(id: ComponentTreeNode['id']) {
+ return !!expandedMap.value[id]
+}
+
+export function useSelectedComponent() {
+ const data = computed(() => selectedComponentData.value)
+ const state = computed(() => selectedComponentData.value
+ ? groupBy(sortByKey(selectedComponentData.value.state.filter((el) => {
+ try {
+ return searchDeepInObject({
+ [el.key]: el.value,
+ }, selectedComponentStateFilter.value)
+ }
+ catch (e) {
+ return {
+ [el.key]: e,
+ }
+ }
+ })), 'type')
+ : ({}))
+
+ const fileIsPath = computed(() => data.value?.file && /[/\\]/.test(data.value.file))
+
+ function inspectDOM() {
+ if (!data.value) {
+ return
+ }
+ if (isChrome) {
+ getBridge().send(BridgeEvents.TO_BACK_COMPONENT_INSPECT_DOM, { instanceId: data.value.id })
+ }
+ else {
+ // eslint-disable-next-line no-alert
+ window.alert('DOM inspection is not supported in this shell.')
+ }
+ }
+
+ function openFile() {
+ if (!data.value) {
+ return
+ }
+ openInEditor(data.value.file)
+ }
+
+ const { bridge } = useBridge()
+
+ function editState(dotPath: string, payload: EditStatePayload, type?: string) {
+ bridge.send(BridgeEvents.TO_BACK_COMPONENT_EDIT_STATE, {
+ instanceId: data.value?.id,
+ dotPath,
+ type,
+ ...payload,
+ })
+ }
+
+ function scrollToComponent() {
+ bridge.send(BridgeEvents.TO_BACK_COMPONENT_SCROLL_TO, {
+ instanceId: data.value?.id,
+ })
+ }
+
+ return {
+ data,
+ state,
+ stateFilter: selectedComponentStateFilter,
+ inspectDOM,
+ fileIsPath,
+ openFile,
+ editState,
+ scrollToComponent,
+ selectedComponentId,
+ }
+}
+
+export const updateTrackingEvents = ref>({})
+export const updateTrackingLimit = ref(Date.now() + 5_000)
+
+export function resetComponents() {
+ rootInstances.value = []
+ componentsMap.value = {}
+ componentsParent = {}
+ updateTrackingEvents.value = {}
+ updateTrackingLimit.value = Date.now() + 5_000
+}
+
+export const requestedComponentTree = new Set()
+
+let requestComponentTreeRetryDelay = 500
+
+export async function requestComponentTree(instanceId: ComponentTreeNode['id'] | null = null, recursively = false) {
+ if (!instanceId) {
+ instanceId = '_root'
+ }
+
+ if (requestedComponentTree.has(instanceId)) {
+ return
+ }
+ requestedComponentTree.add(instanceId)
+
+ await waitForAppSelect()
+
+ _sendTreeRequest(instanceId, recursively)
+ _queueRetryTree(instanceId, recursively)
+}
+
+function _sendTreeRequest(instanceId: ComponentTreeNode['id'], recursively = false) {
+ getBridge().send(BridgeEvents.TO_BACK_COMPONENT_TREE, {
+ instanceId,
+ filter: treeFilter.value,
+ recursively,
+ })
+}
+
+function _queueRetryTree(instanceId: ComponentTreeNode['id'], recursively = false) {
+ setTimeout(() => _retryRequestComponentTree(instanceId, recursively), requestComponentTreeRetryDelay)
+ requestComponentTreeRetryDelay *= 1.5
+}
+
+function _retryRequestComponentTree(instanceId: ComponentTreeNode['id'], recursively = false) {
+ if (rootInstances.value.length) {
+ requestComponentTreeRetryDelay = 500
+ return
+ }
+ _sendTreeRequest(instanceId, recursively)
+ _queueRetryTree(instanceId, recursively)
+}
+
+export function ensureComponentsMapData(data: ComponentTreeNode) {
+ let component = componentsMap.value[data.id]
+ if (!component) {
+ component = addToComponentsMap(data)
+ }
+ else {
+ component = updateComponentsMapData(data)
+ }
+ return component
+}
+
+function ensureComponentsMapChildren(id: string, children: ComponentTreeNode[]) {
+ const result = children.map(child => ensureComponentsMapData(child))
+ for (const child of children) {
+ componentsParent[child.id] = id
+ }
+ return result
+}
+
+function updateComponentsMapData(data: ComponentTreeNode) {
+ const component = componentsMap.value[data.id]
+ for (const key in data) {
+ if (key === 'children') {
+ if (!data.hasChildren || data.children.length) {
+ const children = ensureComponentsMapChildren(component.id, data.children)
+ component[key] = children
+ }
+ }
+ else {
+ component[key] = data[key]
+ }
+ }
+ return component
+}
+
+function addToComponentsMap(data: ComponentTreeNode) {
+ if (!data.hasChildren || data.children.length) {
+ data.children = ensureComponentsMapChildren(data.id, data.children)
+ }
+ componentsMap.value[data.id] = data
+ return data
+}
+
+export async function loadComponent(id: ComponentTreeNode['id']) {
+ if (!id || selectedComponentPendingId.value === id) {
+ return
+ }
+ lastSelectedComponentId[getAppIdFromComponentId(id)] = id
+ setStorage('lastSelectedComponentId', lastSelectedComponentId)
+ selectedComponentPendingId.value = id
+ await waitForAppSelect()
+ getBridge().send(BridgeEvents.TO_BACK_COMPONENT_SELECTED_DATA, id)
+}
+
+export function sortChildren(children: ComponentTreeNode[]) {
+ return children.slice().sort((a, b) => {
+ if (a.inactive && !b.inactive) {
+ return 1
+ }
+ else if (!a.inactive && b.inactive) {
+ return -1
+ }
+ const order = compareIndexLists(a.domOrder ?? [], b.domOrder ?? [])
+ if (order === 0) {
+ return a.id.localeCompare(b.id)
+ }
+ else {
+ return order
+ }
+ })
+}
+
+function compareIndexLists(a: number[], b: number[]): number {
+ if (!a.length || !b.length) {
+ return 0
+ }
+ else if (a[0] === b[0]) {
+ return compareIndexLists(a.slice(1), b.slice(1))
+ }
+ else {
+ return a[0] - b[0]
+ }
+}
+
+export function getAppIdFromComponentId(id: string) {
+ const index = id.indexOf(':')
+ const appId = id.substring(0, index)
+ return appId
+}
+
+export interface ComponentUpdateTrackingEvent {
+ instanceId: string
+ time: number
+ count: number
+}
+
+export function addUpdateTrackingEvent(instanceId: string, time: number) {
+ const event = updateTrackingEvents.value[instanceId]
+ if (event) {
+ event.count++
+ event.time = time
+ }
+ else {
+ updateTrackingEvents.value[instanceId] = {
+ instanceId,
+ time,
+ count: 1,
+ }
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/components/composable/highlight.ts b/vue-devtools/packages/app-frontend/src/features/components/composable/highlight.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f53e6cc2fbf438cea1f6bcd07b8503427fd4612e
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/components/composable/highlight.ts
@@ -0,0 +1,28 @@
+import { getBridge } from '@front/features/bridge'
+import { BridgeEvents } from '@vue-devtools/shared-utils'
+import type { Ref } from 'vue'
+import throttle from 'lodash/throttle'
+
+const throttledSend = throttle((id?: string) => {
+ if (id) {
+ getBridge().send(BridgeEvents.TO_BACK_COMPONENT_MOUSE_OVER, id)
+ }
+ else {
+ getBridge().send(BridgeEvents.TO_BACK_COMPONENT_MOUSE_OUT)
+ }
+}, 200)
+
+export function useComponentHighlight(id: Ref) {
+ function highlight() {
+ throttledSend(id.value)
+ }
+
+ function unhighlight() {
+ throttledSend(null)
+ }
+
+ return {
+ highlight,
+ unhighlight,
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/components/composable/index.ts b/vue-devtools/packages/app-frontend/src/features/components/composable/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..63141a6efe710895c4ee91c29c5362a948eb146a
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/components/composable/index.ts
@@ -0,0 +1,4 @@
+export * from './components'
+export * from './highlight'
+export * from './pick'
+export * from './setup'
diff --git a/vue-devtools/packages/app-frontend/src/features/components/composable/pick.ts b/vue-devtools/packages/app-frontend/src/features/components/composable/pick.ts
new file mode 100644
index 0000000000000000000000000000000000000000..29c3c83235c2503caf60e1babaa778198fb6c7e4
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/components/composable/pick.ts
@@ -0,0 +1,44 @@
+import { ref } from 'vue'
+import { BridgeEvents } from '@vue-devtools/shared-utils'
+import { useBridge } from '@front/features/bridge'
+import { setComponentOpen, useComponentRequests } from '.'
+
+export function useComponentPick() {
+ const { bridge, onBridge } = useBridge()
+ const { selectComponent, requestComponentTree } = useComponentRequests()
+
+ const pickingComponent = ref(false)
+
+ function startPickingComponent() {
+ pickingComponent.value = true
+ bridge.send(BridgeEvents.TO_BACK_COMPONENT_PICK)
+ }
+
+ function stopPickingComponent() {
+ pickingComponent.value = false
+ bridge.send(BridgeEvents.TO_BACK_COMPONENT_PICK_CANCELED)
+ }
+
+ onBridge(BridgeEvents.TO_FRONT_COMPONENT_PICK, ({ id, parentIds }) => {
+ pickingComponent.value = false
+ selectComponent(id)
+ parentIds.reverse().forEach((id) => {
+ // Ignore root
+ if (id.endsWith('root')) {
+ return
+ }
+ setComponentOpen(id, true)
+ requestComponentTree(id)
+ })
+ })
+
+ onBridge(BridgeEvents.TO_FRONT_COMPONENT_PICK_CANCELED, () => {
+ pickingComponent.value = false
+ })
+
+ return {
+ pickingComponent,
+ startPickingComponent,
+ stopPickingComponent,
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/components/composable/setup.ts b/vue-devtools/packages/app-frontend/src/features/components/composable/setup.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7f61dd61b2e9ed852cdf55183389da3748672ae3
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/components/composable/setup.ts
@@ -0,0 +1,86 @@
+import type { Bridge } from '@vue-devtools/shared-utils'
+import { BridgeEvents, getStorage, parse } from '@vue-devtools/shared-utils'
+import { putError } from '@front/features/error'
+import {
+ addUpdateTrackingEvent,
+ ensureComponentsMapData,
+ getAppIdFromComponentId,
+ isComponentOpen,
+ lastSelectedComponentId,
+ loadComponent,
+ requestComponentTree,
+ requestedComponentTree,
+ rootInstances,
+ selectedComponentData,
+ selectedComponentId,
+ selectedComponentPendingId,
+ setComponentOpen,
+} from './components'
+
+export function setupComponentsBridgeEvents(bridge: Bridge) {
+ selectedComponentPendingId.value = null
+
+ bridge.on(BridgeEvents.TO_FRONT_COMPONENT_TREE, ({ instanceId, treeData, notFound }) => {
+ requestedComponentTree.delete(instanceId)
+
+ const isRoot = instanceId.endsWith('root')
+
+ // Not supported
+ if (!treeData) {
+ if (isRoot && !notFound) {
+ putError('Component tree not supported')
+ }
+ return
+ }
+
+ // Handle tree data
+ const data = parse(treeData)
+ if (isRoot) {
+ rootInstances.value = data.map(i => ensureComponentsMapData(i))
+ }
+ else {
+ for (const child of data) {
+ ensureComponentsMapData(child)
+ }
+ }
+
+ // Try to load selected component again
+ if (isRoot && selectedComponentId.value && !selectedComponentData.value && !selectedComponentPendingId.value
+ && getAppIdFromComponentId(selectedComponentId.value) === getAppIdFromComponentId(instanceId)) {
+ loadComponent(selectedComponentId.value)
+ }
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_COMPONENT_SELECTED_DATA, ({ instanceId, data, parentIds }) => {
+ if (instanceId === selectedComponentId.value) {
+ selectedComponentData.value = parse(data)
+ }
+ if (instanceId === selectedComponentPendingId.value) {
+ selectedComponentPendingId.value = null
+ }
+ if (parentIds) {
+ parentIds.reverse().forEach((id) => {
+ // Ignore root
+ if (id.endsWith('root')) {
+ return
+ }
+ if (!isComponentOpen(id)) {
+ setComponentOpen(id, true)
+ requestComponentTree(id)
+ }
+ })
+ }
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_COMPONENT_INSPECT_DOM, () => {
+ chrome.devtools.inspectedWindow.eval('inspect(window.__VUE_DEVTOOLS_INSPECT_TARGET__)')
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_COMPONENT_UPDATED, ({ instanceId, time }) => {
+ addUpdateTrackingEvent(instanceId, time)
+ })
+
+ // Persistance
+
+ Object.assign(lastSelectedComponentId, getStorage('lastSelectedComponentId', {}))
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/connection/AppConnecting.vue b/vue-devtools/packages/app-frontend/src/features/connection/AppConnecting.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d20c036430ba70a3b0b2da0f1327daa575582507
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/connection/AppConnecting.vue
@@ -0,0 +1,43 @@
+
+
+
+
+

+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/connection/AppDisconnected.vue b/vue-devtools/packages/app-frontend/src/features/connection/AppDisconnected.vue
new file mode 100644
index 0000000000000000000000000000000000000000..42af836dc20674438fa5fa79859b3f93ee635366
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/connection/AppDisconnected.vue
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/connection/index.ts b/vue-devtools/packages/app-frontend/src/features/connection/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a60e2cb9c3ee48f76a68b404801bf2aa76de5aff
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/connection/index.ts
@@ -0,0 +1,56 @@
+import { computed, ref } from 'vue'
+import { useNow } from '@vueuse/core'
+
+const isConnected = ref(false)
+const isInitializing = ref(true)
+const lastDisconnect = ref(0)
+const reloadTimes = ref(0)
+let reloadRegistered = false
+
+export function useAppConnection() {
+ const now = useNow({
+ interval: 1000,
+ })
+ const showDisplayDisconnected = computed(() => {
+ if (isInitializing.value) {
+ return false
+ }
+ if (lastDisconnect.value === 0) {
+ return false
+ }
+ // Wait for 5 seconds before showing the disconnected message
+ return !isConnected && now.value.getTime() - lastDisconnect.value > 5000
+ })
+
+ return {
+ isConnected,
+ isInitializing,
+ lastDisconnect,
+ showDisplayDisconnected,
+ reloadTimes,
+ }
+}
+
+export function setAppConnected(value: boolean, force = false, fromReload = false) {
+ // We got disconnected from a page reload
+ if (!value) {
+ reloadRegistered = fromReload
+ }
+
+ if (force) {
+ lastDisconnect.value = 0
+ }
+ else if (!value && isConnected.value) {
+ lastDisconnect.value = Date.now()
+ }
+ isConnected.value = value
+
+ // We are reconnected after a page reload
+ if (value && reloadRegistered) {
+ reloadTimes.value++
+ }
+}
+
+export function setAppInitializing(value: boolean) {
+ isInitializing.value = value
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/error/ErrorOverlay.vue b/vue-devtools/packages/app-frontend/src/features/error/ErrorOverlay.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b0c0adde09c5b063a6d59f6e24f6f832bfc5afc1
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/error/ErrorOverlay.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+ {{ error.message }}
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/error/index.ts b/vue-devtools/packages/app-frontend/src/features/error/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a4ecce760523d3a6c51d9bdbb8af4980c08ddfd3
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/error/index.ts
@@ -0,0 +1,34 @@
+import { computed, ref } from 'vue'
+
+export interface ErrorMessage {
+ message: string
+ icon: string
+}
+
+const errors = ref([])
+
+export function putError(message: string, icon: string = null) {
+ // Dedupe
+ if (errors.value.find(e => e.message === message)) {
+ return
+ }
+
+ errors.value.push({
+ message,
+ icon,
+ })
+}
+
+export function clearError() {
+ errors.value.shift()
+}
+
+export function useError() {
+ const error = computed(() => errors.value[0])
+
+ return {
+ error,
+ putError,
+ clearError,
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/header/AppHeader.vue b/vue-devtools/packages/app-frontend/src/features/header/AppHeader.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b363e1c1b9813a99611ef8efb69afc5e62cd2d9d
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/header/AppHeader.vue
@@ -0,0 +1,261 @@
+
+
+
+
+
+

+
+
route && $router.push(route.targetRoute)"
+ >
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ More settings
+
+
+
+ Devtools plugins
+
+
+
+
+
+ Documentation
+
+
+
+ Report a bug
+
+
+
+ What's new
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/header/AppHeaderSelect.vue b/vue-devtools/packages/app-frontend/src/features/header/AppHeaderSelect.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a7470cfcd1d6b76d55f03326bd644584ac82ff50
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/header/AppHeaderSelect.vue
@@ -0,0 +1,264 @@
+
+
+
+
+
+
+
+
+
+ {{ selectedItem.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+ Scroll to switch
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/header/AppHistoryNav.vue b/vue-devtools/packages/app-frontend/src/features/header/AppHistoryNav.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1b42b1e43e03688afb9aa51b07181dd31a690533
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/header/AppHistoryNav.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/header/header.ts b/vue-devtools/packages/app-frontend/src/features/header/header.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b41cdd19695347162d4745d3ce4a8b11eab77253
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/header/header.ts
@@ -0,0 +1,3 @@
+import { ref } from 'vue'
+
+export const showAppsSelector = ref(true)
diff --git a/vue-devtools/packages/app-frontend/src/features/header/tabs.ts b/vue-devtools/packages/app-frontend/src/features/header/tabs.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c1003f8e448e7360809b0ddc6ccf9c39e33a90a8
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/header/tabs.ts
@@ -0,0 +1,17 @@
+import { computed } from 'vue'
+import { useRoute } from 'vue-router'
+
+export function useTabs() {
+ const route = useRoute()
+ const currentTab = computed(() => {
+ let fromMeta = route.meta.tab
+ if (typeof fromMeta === 'function') {
+ fromMeta = fromMeta(route)
+ }
+ return (fromMeta || route.name) as string
+ })
+
+ return {
+ currentTab,
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/inspector/DataField.vue b/vue-devtools/packages/app-frontend/src/features/inspector/DataField.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d824c4c3dfefb42ef5c617d6f2245596fe59a722
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/inspector/DataField.vue
@@ -0,0 +1,804 @@
+
+
+
+
+
+
+
+
+
+ {{ displayedKey }}:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ valueDetails }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $emit('editState', path, payload)"
+ />
+
+ $emit('editState', path, payload)"
+ />
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/inspector/StateFields.vue b/vue-devtools/packages/app-frontend/src/features/inspector/StateFields.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e2ec39a6097ab532264d3880e6daa9228761156a
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/inspector/StateFields.vue
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+
+ {{ field.key }}:
+
+
{{ fieldErrors[field.key] }}
+
+
+ $emit('editState', path, payload)"
+ />
+
+
+
+
+
+
+ {{ key }}:
+
+
{{ fieldErrors[key] }}
+
+
+ $emit('editState', path, payload)"
+ />
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/inspector/StateInspector.vue b/vue-devtools/packages/app-frontend/src/features/inspector/StateInspector.vue
new file mode 100644
index 0000000000000000000000000000000000000000..6ebc1cc55d82b8a60e280568507cfd3cbcdd89e8
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/inspector/StateInspector.vue
@@ -0,0 +1,135 @@
+
+
+
+
+
+ $emit('editState', path, payload, dataType)"
+ />
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/inspector/StateType.vue b/vue-devtools/packages/app-frontend/src/features/inspector/StateType.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c1fd3d5f50756ba2ec597c2baa65edd8249520af
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/inspector/StateType.vue
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+ {{ toDisplayType(dataType) }}
+
+
+
+
+
+
+
$emit('editState', path, payload)"
+ />
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/inspector/custom/CustomInspector.vue b/vue-devtools/packages/app-frontend/src/features/inspector/custom/CustomInspector.vue
new file mode 100644
index 0000000000000000000000000000000000000000..85359cfd959817c081cdc595ef1269dca813ff48
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/inspector/custom/CustomInspector.vue
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
Inspector {{ $route.params.inspectorId }} not found
+
Go back
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/inspector/custom/CustomInspectorNode.vue b/vue-devtools/packages/app-frontend/src/features/inspector/custom/CustomInspectorNode.vue
new file mode 100644
index 0000000000000000000000000000000000000000..733324702e873ebc1071add5dab5b73cd1665a14
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/inspector/custom/CustomInspectorNode.vue
@@ -0,0 +1,232 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ node.label }}
+
+
+
+ {{ tag.label }}
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/inspector/custom/CustomInspectorSelectedNodePane.vue b/vue-devtools/packages/app-frontend/src/features/inspector/custom/CustomInspectorSelectedNodePane.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f5a3d3261bbfd24dbf6bb15d1ce0ed0e9f070e42
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/inspector/custom/CustomInspectorSelectedNodePane.vue
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+ {{ inspector.selectedNode.label }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ inspector.noSelectionText }}
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/inspector/custom/composable.ts b/vue-devtools/packages/app-frontend/src/features/inspector/custom/composable.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c0244207457884f5c6c68cd37e88f64b1b8831b4
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/inspector/custom/composable.ts
@@ -0,0 +1,217 @@
+import { computed, ref } from 'vue'
+import { useRoute } from 'vue-router'
+import { useApps } from '@front/features/apps'
+import type { Bridge } from '@vue-devtools/shared-utils'
+import { BridgeEvents, getStorage, parse, searchDeepInObject, setStorage } from '@vue-devtools/shared-utils'
+import { getBridge, useBridge } from '@front/features/bridge'
+
+export interface InspectorFromBackend {
+ id: string
+ appId: string
+ pluginId: string
+ label: string
+ icon: string
+ treeFilterPlaceholder: string
+ stateFilterPlaceholder: string
+ noSelectionText: string
+ actions?: {
+ icon: string
+ tooltip?: string
+ }[]
+ nodeActions?: {
+ icon: string
+ tooltip?: string
+ }[]
+}
+
+export interface Inspector extends InspectorFromBackend {
+ rootNodes: any[]
+ treeFilter: string
+ selectedNodeId: string
+ selectedNode: any
+ stateFilter: string
+ state: any
+ expandedMap: Record
+}
+
+const SELECTED_NODES_STORAGE = 'custom-inspector-selected-nodes'
+let selectedIdsStorage = {}
+
+function inspectorFactory(options: InspectorFromBackend): Inspector {
+ return {
+ ...options,
+ rootNodes: [],
+ treeFilter: '',
+ selectedNodeId: selectedIdsStorage[options.id] || null,
+ selectedNode: null,
+ stateFilter: '',
+ state: null,
+ expandedMap: {},
+ }
+}
+
+const inspectors = ref([])
+
+export function useInspectors() {
+ const { currentAppId } = useApps()
+ const currentAppInspectors = computed(() => inspectors.value.filter(i => i.appId === currentAppId.value))
+
+ return {
+ inspectors: currentAppInspectors,
+ }
+}
+
+export function useCurrentInspector() {
+ const route = useRoute()
+ const { inspectors } = useInspectors()
+ const { bridge } = useBridge()
+
+ const currentInspector = computed(() => inspectors.value.find(i => i.id === route.params.inspectorId))
+
+ const filteredState = computed(() => {
+ if (currentInspector.value?.stateFilter) {
+ const result = {}
+ for (const groupKey in currentInspector.value.state) {
+ const group = currentInspector.value.state[groupKey]
+ const groupFields = group.filter(el => searchDeepInObject({
+ [el.key]: el.value,
+ }, currentInspector.value?.stateFilter))
+ if (groupFields.length) {
+ result[groupKey] = groupFields
+ }
+ }
+ return result
+ }
+ else {
+ return currentInspector.value?.state
+ }
+ })
+
+ function selectNode(node) {
+ currentInspector.value.selectedNodeId = node.id
+ currentInspector.value.selectedNode = node
+ selectedIdsStorage[currentInspector.value.id] = node.id
+ setStorage(SELECTED_NODES_STORAGE, selectedIdsStorage)
+ fetchState(currentInspector.value)
+ }
+
+ function refreshInspector() {
+ refreshTree()
+ refreshState()
+ }
+
+ function refreshTree() {
+ fetchTree(currentInspector.value)
+ }
+
+ function refreshState() {
+ fetchState(currentInspector.value)
+ }
+
+ function editState(path: string, payload: any, type: string) {
+ bridge.send(BridgeEvents.TO_BACK_CUSTOM_INSPECTOR_EDIT_STATE, {
+ inspectorId: currentInspector.value.id,
+ appId: currentInspector.value.appId,
+ nodeId: currentInspector.value.selectedNodeId,
+ path,
+ type,
+ payload,
+ })
+ }
+
+ return {
+ currentInspector,
+ filteredState,
+ selectNode,
+ refreshInspector,
+ refreshTree,
+ refreshState,
+ editState,
+ }
+}
+
+function fetchInspectors() {
+ getBridge().send(BridgeEvents.TO_BACK_CUSTOM_INSPECTOR_LIST, {})
+}
+
+function fetchTree(inspector: Inspector) {
+ if (!inspector) {
+ return
+ }
+ getBridge().send(BridgeEvents.TO_BACK_CUSTOM_INSPECTOR_TREE, {
+ inspectorId: inspector.id,
+ appId: inspector.appId,
+ treeFilter: inspector.treeFilter,
+ })
+}
+
+function fetchState(inspector: Inspector) {
+ if (!inspector || !inspector.selectedNodeId) {
+ return
+ }
+ getBridge().send(BridgeEvents.TO_BACK_CUSTOM_INSPECTOR_STATE, {
+ inspectorId: inspector.id,
+ appId: inspector.appId,
+ nodeId: inspector.selectedNodeId,
+ })
+}
+
+export function resetInspectors() {
+ inspectors.value = []
+ fetchInspectors()
+}
+
+export function setupCustomInspectorBridgeEvents(bridge: Bridge) {
+ selectedIdsStorage = getStorage(SELECTED_NODES_STORAGE, {})
+
+ bridge.on(BridgeEvents.TO_FRONT_CUSTOM_INSPECTOR_LIST, ({ inspectors: list }) => {
+ list.forEach((inspector) => {
+ if (!inspectors.value.some(i => i.id === inspector.id && i.appId === inspector.appId)) {
+ inspectors.value.push(inspectorFactory(inspector))
+ }
+ })
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_CUSTOM_INSPECTOR_ADD, () => {
+ fetchInspectors()
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_CUSTOM_INSPECTOR_TREE, ({ appId, inspectorId, rootNodes }) => {
+ const inspector = inspectors.value.find(i => i.id === inspectorId && i.appId === appId)
+
+ if (!inspector) {
+ console.warn(`Inspector ${inspectorId} not found`)
+ return
+ }
+
+ inspector.rootNodes = rootNodes
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_CUSTOM_INSPECTOR_STATE, ({ appId, inspectorId, state }) => {
+ const inspector = inspectors.value.find(i => i.id === inspectorId && i.appId === appId)
+
+ if (!inspector) {
+ console.warn(`Inspector ${inspectorId} not found`)
+ return
+ }
+
+ inspector.state = parse(state)
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_CUSTOM_INSPECTOR_SELECT_NODE, ({ appId, inspectorId, nodeId }) => {
+ const inspector = inspectors.value.find(i => i.id === inspectorId && i.appId === appId)
+
+ if (!inspector) {
+ console.warn(`Inspector ${inspectorId} not found`)
+ return
+ }
+
+ inspector.selectedNodeId = nodeId
+ inspector.selectedNode = null
+ selectedIdsStorage[inspector.id] = nodeId
+ setStorage(SELECTED_NODES_STORAGE, selectedIdsStorage)
+ fetchState(inspector)
+ })
+
+ resetInspectors()
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/layout/EmptyPane.vue b/vue-devtools/packages/app-frontend/src/features/layout/EmptyPane.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0633bcee22c007f43a8ca81c1ee96115d25cae0a
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/layout/EmptyPane.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/layout/SplitPane.vue b/vue-devtools/packages/app-frontend/src/features/layout/SplitPane.vue
new file mode 100644
index 0000000000000000000000000000000000000000..11467dbe4634025e7003c4f8de237087e2b86211
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/layout/SplitPane.vue
@@ -0,0 +1,307 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/layout/orientation.ts b/vue-devtools/packages/app-frontend/src/features/layout/orientation.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5dd85de504840677642122ab7cb591fb6af77b53
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/layout/orientation.ts
@@ -0,0 +1,17 @@
+import { ref } from 'vue'
+
+const orientation = ref('landscape')
+
+export function useOrientation() {
+ return {
+ orientation,
+ }
+}
+
+const mediaQuery = window.matchMedia('(min-width: 685px)')
+switchOrientation(mediaQuery)
+mediaQuery.addEventListener('change', switchOrientation)
+
+function switchOrientation(mediaQueryEvent: MediaQueryListEvent | MediaQueryList) {
+ orientation.value = mediaQueryEvent.matches ? 'landscape' : 'portrait'
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/plugin/PluginDetails.vue b/vue-devtools/packages/app-frontend/src/features/plugin/PluginDetails.vue
new file mode 100644
index 0000000000000000000000000000000000000000..5c6ede62d9129d880faab3ed6405f3653b6a1d25
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/plugin/PluginDetails.vue
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
+
+
![Plugin logo]()
+
+
+
+
+ {{ plugin.label }}
+
+
+
+ ID: {{ plugin.id }}
+
+
+ Package: {{ plugin.packageName }}
+
+
+
+
+
+
+
+
+ Permissions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Plugin not found
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/plugin/PluginHome.vue b/vue-devtools/packages/app-frontend/src/features/plugin/PluginHome.vue
new file mode 100644
index 0000000000000000000000000000000000000000..321fc583384913a0bc2488c7282a4f86930c30e9
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/plugin/PluginHome.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+ No plugins found
+
+
+
+

+
+
+ Devtools plugins are added by packages in your application. They can provide new features to the Vue devtools, such as custom inspectors, additional component data or timeline layers.
+
+
+
+
+ Create your own Plugin
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/plugin/PluginListItem.vue b/vue-devtools/packages/app-frontend/src/features/plugin/PluginListItem.vue
new file mode 100644
index 0000000000000000000000000000000000000000..acb08ba2a671fa929dca26c93a0cf7805f5f9caa
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/plugin/PluginListItem.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+ {{ plugin.label }}
+
+
+ disabled
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/plugin/PluginPermission.vue b/vue-devtools/packages/app-frontend/src/features/plugin/PluginPermission.vue
new file mode 100644
index 0000000000000000000000000000000000000000..bb5f7f52c4f8d6f8851372b39eeea12c905f5b51
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/plugin/PluginPermission.vue
@@ -0,0 +1,49 @@
+
+
+
+
+ {{ label }}
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/plugin/PluginSettings.vue b/vue-devtools/packages/app-frontend/src/features/plugin/PluginSettings.vue
new file mode 100644
index 0000000000000000000000000000000000000000..3fd1e1c0f52df25bc87e4768877bb460344f8d45
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/plugin/PluginSettings.vue
@@ -0,0 +1,71 @@
+
+
+
+
+ No settings found for this plugin
+
+
+
+
+ Plugin settings
+
+
+
updateValue(id, value)"
+ />
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/plugin/PluginSettingsItem.vue b/vue-devtools/packages/app-frontend/src/features/plugin/PluginSettingsItem.vue
new file mode 100644
index 0000000000000000000000000000000000000000..74c07aa744149a9635441e21a042ab72bd60922e
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/plugin/PluginSettingsItem.vue
@@ -0,0 +1,114 @@
+
+
+
+
+
+
{{ schema.label }}
+
+ {{ schema.description }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/plugin/PluginSourceDescription.vue b/vue-devtools/packages/app-frontend/src/features/plugin/PluginSourceDescription.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7fd879479888139b2373ee14320ad7704ec8fcdd
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/plugin/PluginSourceDescription.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+
![Plugin logo]()
+
+
+
+
Provided by {{ plugin ? plugin.label : pluginId }}
+
+
Plugin ID: {{ plugin.id }}
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/plugin/PluginSourceIcon.vue b/vue-devtools/packages/app-frontend/src/features/plugin/PluginSourceIcon.vue
new file mode 100644
index 0000000000000000000000000000000000000000..85a3045e74976c52299dc7d35f088b50b1f84e36
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/plugin/PluginSourceIcon.vue
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/plugin/Plugins.vue b/vue-devtools/packages/app-frontend/src/features/plugin/Plugins.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4720b716557227bfa2af65fbe00be37514e703b3
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/plugin/Plugins.vue
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Settings
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/plugin/index.ts b/vue-devtools/packages/app-frontend/src/features/plugin/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ed4fdba0253607d763a71e707839d134b18288fc
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/plugin/index.ts
@@ -0,0 +1,85 @@
+import { computed, ref } from 'vue'
+import type { PluginDescriptor } from '@vue/devtools-api'
+import type { Bridge } from '@vue-devtools/shared-utils'
+import { BridgeEvents } from '@vue-devtools/shared-utils'
+import { getBridge } from '@front/features/bridge'
+import { useCurrentApp } from '@front/features/apps'
+
+export interface Plugin {
+ id: string
+ label: string
+ appId: string
+ packageName: string
+ homepage: string
+ logo: string
+ componentStateTypes: string[]
+ settingsSchema?: PluginDescriptor['settings']
+}
+
+interface PluginsPerApp {
+ [appId: string]: Plugin[]
+}
+
+const pluginsPerApp = ref({})
+
+function getPlugins(appId: string) {
+ let plugins = pluginsPerApp.value[appId]
+ if (!plugins) {
+ plugins = []
+ pluginsPerApp.value[appId] = plugins
+ // Read the property again to make it reactive
+ plugins = pluginsPerApp.value[appId]
+ }
+ return plugins
+}
+
+function fetchPlugins() {
+ getBridge().send(BridgeEvents.TO_BACK_DEVTOOLS_PLUGIN_LIST, {})
+}
+
+export function usePlugins() {
+ const { currentAppId } = useCurrentApp()
+
+ const plugins = computed(() => getPlugins(currentAppId.value))
+
+ return {
+ plugins,
+ }
+}
+
+export function useComponentStateTypePlugin() {
+ const { plugins } = usePlugins()
+
+ function getStateTypePlugin(type: string) {
+ return plugins.value.find(p => p.componentStateTypes?.includes(type))
+ }
+
+ return {
+ getStateTypePlugin,
+ }
+}
+
+function addPlugin(plugin: Plugin) {
+ const list = getPlugins(plugin.appId)
+ const index = list.findIndex(p => p.id === plugin.id)
+ if (index !== -1) {
+ list.splice(index, 1, plugin)
+ }
+ else {
+ list.push(plugin)
+ }
+}
+
+export function setupPluginsBridgeEvents(bridge: Bridge) {
+ bridge.on(BridgeEvents.TO_FRONT_DEVTOOLS_PLUGIN_ADD, async ({ plugin }) => {
+ await addPlugin(plugin)
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_DEVTOOLS_PLUGIN_LIST, async ({ plugins }) => {
+ for (const plugin of plugins) {
+ await addPlugin(plugin)
+ }
+ })
+
+ fetchPlugins()
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/settings/GlobalSettings.vue b/vue-devtools/packages/app-frontend/src/features/settings/GlobalSettings.vue
new file mode 100644
index 0000000000000000000000000000000000000000..3fec603cbac8a902f61e2a572f289f49c64aa4a7
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/settings/GlobalSettings.vue
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Collapse app selector
+
+
+
+
+
+ Enable
+
+
+ Useful for trackpads
+
+
+
+
+
+ Enable
+
+
+
+ Clear storage
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Enable
+
+
+ Turn off if your app is slowed down
+
+
+
+
+
+ Enable
+
+
+ Turn off if your app is slowed down
+
+
+
+
+
+ Enable
+
+
+ May print warnings in the console
+
+
+
+
+
+ Enable
+
+
+ Don't enable if you are sensitive to flashing
+
+
+
+
+
+
+
+ Hide timeline canvas
+
+
+ Hide events explorer
+
+
+
+
+
+ Enable
+
+
+
+
+
+ Enable
+
+
+
+
+
+
+
+ Are you sure you want to clear all storage?
+
+
+
+ Cancel
+
+
+ Clear
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/settings/NewTag.vue b/vue-devtools/packages/app-frontend/src/features/settings/NewTag.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b9ea5061fd17d894182072281a25a6b40a46cc22
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/settings/NewTag.vue
@@ -0,0 +1,37 @@
+
+
+
+
+ New
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/AskScreenshotPermission.vue b/vue-devtools/packages/app-frontend/src/features/timeline/AskScreenshotPermission.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a70dacbc54a5a1abcabfb7c6dd37e097add3450d
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/AskScreenshotPermission.vue
@@ -0,0 +1,72 @@
+
+
+
+
+
+
Taking screenshots requires permission to access the Tabs API which also includes access to other information about your tabs.
+
Please note that we will only use this permission to take screenshots of the current tab.
+
+
+
+
+
+ Cancel
+
+
+ Request permission
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/LayerItem.vue b/vue-devtools/packages/app-frontend/src/features/timeline/LayerItem.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e9d776c4060a5f7e1da2a008dd47795b43a29e22
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/LayerItem.vue
@@ -0,0 +1,175 @@
+
+
+
+
+
+
+
+
+
+
{{ layer.label }}
+
+
+
+
+
+
+ {{ $shared.componentEventsEnabled ? 'Disable' : 'Enable' }}
+
+
+
+ {{ $shared.performanceMonitoringEnabled ? 'Disable' : 'Enable' }}
+
+
+
+ Select
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/Timeline.vue b/vue-devtools/packages/app-frontend/src/features/timeline/Timeline.vue
new file mode 100644
index 0000000000000000000000000000000000000000..81f5b32f3ff6db72ef63e47794279757eabe3997
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/Timeline.vue
@@ -0,0 +1,628 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ layers.length }} layer{{ layers.length === 1 ? '' : 's' }}
+
+
+
+
+
+
setLayerHidden(layer, !value)"
+ >
+
+
+
+
+ {{ layer.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Not recording
+
+
+
+
+
+
+
+
+ Hide timeline canvas
+
+
+
+ Hide events explorer
+
+
+
+ Time grid
+
+
+
+ Screenshots
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formattedCursorTime }}
+
+ ({{ Math.floor(startTime) }}|{{ Math.floor(cursorTime) }}|{{ Math.floor(endTime) }})
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/TimelineEventInspector.vue b/vue-devtools/packages/app-frontend/src/features/timeline/TimelineEventInspector.vue
new file mode 100644
index 0000000000000000000000000000000000000000..97e7b6313c52e09ea064485fb791b12ec2a25d82
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/TimelineEventInspector.vue
@@ -0,0 +1,150 @@
+
+
+
+
+
+
+
+ Time: {{ inspectedEvent.time }}
+
+
+
+
+
+
+
+
+
+
+
+
+ Select an event to display details
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/TimelineEventList.vue b/vue-devtools/packages/app-frontend/src/features/timeline/TimelineEventList.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0f35985853126db89e1a8d9838bed6611e0015e5
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/TimelineEventList.vue
@@ -0,0 +1,283 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Select a layer to get started
+
+
+ No events
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/TimelineEventListItem.vue b/vue-devtools/packages/app-frontend/src/features/timeline/TimelineEventListItem.vue
new file mode 100644
index 0000000000000000000000000000000000000000..6597ca84a85fd419b25ae5786b6b98a4da195cef
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/TimelineEventListItem.vue
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+ {{ event.title || 'Event' }}
+
+
+
+
+
+
+
+
+
+
+ selected
+
+
+
+ {{ time }}
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/TimelineScrollbar.vue b/vue-devtools/packages/app-frontend/src/features/timeline/TimelineScrollbar.vue
new file mode 100644
index 0000000000000000000000000000000000000000..976145170ef995608bdad88aa143df9cedc8d067
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/TimelineScrollbar.vue
@@ -0,0 +1,194 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/TimelineView.vue b/vue-devtools/packages/app-frontend/src/features/timeline/TimelineView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7f788121ffecb802a5350b0a3f4dae4432d9aea2
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/TimelineView.vue
@@ -0,0 +1,1492 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/composable/events.ts b/vue-devtools/packages/app-frontend/src/features/timeline/composable/events.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1ec91237f21b978ce906ea7f0a99ad10ff88d641
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/composable/events.ts
@@ -0,0 +1,161 @@
+import { computed, onUnmounted, watch } from 'vue'
+import { BridgeEvents, setStorage } from '@vue-devtools/shared-utils'
+import { getBridge } from '@front/features/bridge'
+import { formatTime } from '@front/util/format'
+import { addNonReactiveProperties } from '@front/util/reactivity'
+import type {
+ Layer,
+ TimelineEvent,
+} from './store'
+import {
+ endTime,
+ inspectedEvent,
+ inspectedEventData,
+ inspectedEventPendingId,
+ maxTime,
+ minTime,
+ selectedEvent,
+ selectedLayer,
+ startTime,
+ timelineIsEmpty,
+} from './store'
+import { resetTime } from './reset'
+import { takeScreenshot } from './screenshot'
+import { addGroupAroundPosition } from './layers'
+import type { EventGroup } from '.'
+
+const AUTOSCROLL_DURATION = 10_000_000
+
+type AddEventCb = (event: TimelineEvent) => void
+
+const addEventCbs: AddEventCb[] = []
+
+export function onEventAdd(cb: AddEventCb) {
+ onUnmounted(() => {
+ const index = addEventCbs.indexOf(cb)
+ if (index !== -1) {
+ addEventCbs.splice(index, 1)
+ }
+ })
+
+ addEventCbs.push(cb)
+}
+
+export function addEvent(appId: string, eventOptions: TimelineEvent, layer: Layer) {
+ // Non-reactive content
+ const event = {} as TimelineEvent
+ addNonReactiveProperties(event, eventOptions)
+
+ if (layer.eventsMap[event.id]) {
+ return
+ }
+
+ if (timelineIsEmpty.value) {
+ timelineIsEmpty.value = false
+ resetTime()
+ }
+
+ addNonReactiveProperties(event, {
+ layer,
+ appId,
+ })
+ layer.events.push(event)
+ layer.eventsMap[event.id] = event
+
+ // Groups
+ if (event.groupId != null) {
+ let group = layer.groupsMap[event.groupId]
+ if (!group) {
+ group = layer.groupsMap[event.groupId] = {
+ events: [],
+ duration: 0,
+ } as EventGroup
+ addNonReactiveProperties(group, {
+ id: event.groupId,
+ y: 0,
+ firstEvent: event,
+ lastEvent: event,
+ nonReactiveDuration: 0,
+ oldSize: null,
+ oldSelected: null,
+ })
+ layer.groups.push(group)
+ }
+ addGroupAroundPosition(layer, group, event.time)
+ group.events.push(event)
+ group.lastEvent = event
+ group.duration = group.nonReactiveDuration = event.time - group.firstEvent.time
+ event.group = group
+ }
+
+ // Min time
+ if (minTime.value === -1_000_000 || minTime.value > event.time) {
+ const stick = minTime.value === startTime.value
+ minTime.value = event.time - 100_000
+ if (stick) {
+ startTime.value = minTime.value
+ }
+ }
+
+ // Update scrollbar
+ const scrollTime = event.time + 100_000
+ if (scrollTime > maxTime.value) {
+ if (endTime.value === maxTime.value) {
+ if (startTime.value !== minTime.value) {
+ // Autoscroll
+ startTime.value = scrollTime - (endTime.value - startTime.value)
+ }
+ else if (endTime.value - startTime.value > AUTOSCROLL_DURATION) {
+ // Autoscroll
+ startTime.value = scrollTime - AUTOSCROLL_DURATION
+ }
+ endTime.value = scrollTime
+ }
+ maxTime.value = scrollTime
+ }
+
+ takeScreenshot(event)
+
+ for (const cb of addEventCbs) {
+ cb(event)
+ }
+}
+
+export function useSelectedEvent() {
+ return {
+ selectedEvent: computed(() => selectedEvent.value),
+ selectedGroupEvents: computed(() => selectedEvent.value?.group?.events ?? []),
+ }
+}
+
+export function useInspectedEvent() {
+ watch(inspectedEvent, (event) => {
+ if (event) {
+ loadEvent(event.id)
+ event.layer.lastInspectedEvent = event
+ }
+ }, {
+ immediate: true,
+ })
+
+ return {
+ inspectedEvent,
+ inspectedEventState: computed(() => inspectedEventData.value),
+ time: computed(() => formatTime(inspectedEvent.value.time / 1000, 'ms')),
+ loading: computed(() => inspectedEventPendingId.value != null),
+ }
+}
+
+function loadEvent(id: TimelineEvent['id']) {
+ if (id == null || inspectedEventPendingId.value === id) {
+ return
+ }
+ inspectedEventPendingId.value = id
+ getBridge().send(BridgeEvents.TO_BACK_TIMELINE_EVENT_DATA, { id })
+}
+
+export function selectEvent(event: TimelineEvent) {
+ selectedEvent.value = inspectedEvent.value = event
+ selectedLayer.value = event.layer
+ setStorage('selected-layer-id', event.layer.id)
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/composable/index.ts b/vue-devtools/packages/app-frontend/src/features/timeline/composable/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b761f78d50c5c6fba0f2fcae823b5697ef839c4d
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/composable/index.ts
@@ -0,0 +1,8 @@
+export * from './events'
+export * from './layers'
+export * from './markers'
+export * from './reset'
+export * from './screenshot'
+export * from './setup'
+export * from './store'
+export * from './time'
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/composable/layers.ts b/vue-devtools/packages/app-frontend/src/features/timeline/composable/layers.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cae67ae29afd2defe95f8648a690deab8a94c17f
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/composable/layers.ts
@@ -0,0 +1,170 @@
+import { computed } from 'vue'
+import { BridgeEvents, setStorage } from '@vue-devtools/shared-utils'
+import { useApps, waitForAppSelect } from '@front/features/apps'
+import { getBridge } from '@front/features/bridge'
+import { useRouter } from 'vue-router'
+import { addNonReactiveProperties } from '@front/util/reactivity'
+import type {
+ EventGroup,
+ Layer,
+ LayerFromBackend,
+} from './store'
+import {
+ hiddenLayersPerApp,
+ hoverLayerId,
+ inspectedEvent,
+ layersPerApp,
+ selectedEvent,
+ selectedLayer,
+ vScrollPerApp,
+} from './store'
+
+export function layerFactory(options: LayerFromBackend): Layer {
+ const result = {} as Layer
+ addNonReactiveProperties(result, {
+ ...options,
+ newHeight: 1,
+ eventsMap: {},
+ groupsMap: {},
+ groupPositionCache: {},
+ })
+ Object.assign(result, {
+ events: [],
+ groups: [],
+ height: 1,
+ lastInspectedEvent: null,
+ loaded: false,
+ })
+ return result
+}
+
+export function getLayers(appId: string) {
+ let layers = layersPerApp.value[appId]
+ if (!layers || !Array.isArray(layers)) {
+ layersPerApp.value[appId] = []
+ layers = layersPerApp.value[appId]
+ }
+ return layers
+}
+
+function getHiddenLayers(appId: string) {
+ let layers = hiddenLayersPerApp.value[appId]
+ if (!layers || !Array.isArray(layers)) {
+ hiddenLayersPerApp.value[appId] = []
+ layers = hiddenLayersPerApp.value[appId]
+ }
+ return layers
+}
+
+export function useLayers() {
+ const { currentAppId } = useApps()
+
+ const allLayers = computed(() => getLayers(currentAppId.value))
+
+ function isLayerHidden(layer: Layer) {
+ const list = getHiddenLayers(currentAppId.value)
+ return list.includes(layer.id)
+ }
+
+ function resetSelectedStatus() {
+ selectedLayer.value = null
+ inspectedEvent.value = null
+ selectedEvent.value = null
+ hoverLayerId.value = null
+ setStorage('selected-layer-id', '')
+ }
+
+ function setLayerHidden(layer: Layer, hidden: boolean) {
+ const list = getHiddenLayers(currentAppId.value)
+ const index = list.indexOf(layer.id)
+
+ if (selectedLayer.value === layer) {
+ resetSelectedStatus()
+ }
+
+ if (hidden && index === -1) {
+ list.push(layer.id)
+ }
+ else if (!hidden && index !== -1) {
+ list.splice(index, 1)
+ }
+ setStorage('hidden-layers', hiddenLayersPerApp.value)
+ }
+
+ const layers = computed(() => allLayers.value.filter(l => !isLayerHidden(l)))
+
+ const router = useRouter()
+
+ function selectLayer(layer: Layer) {
+ let event = selectedLayer.value !== layer ? layer.lastInspectedEvent : null
+
+ selectedLayer.value = layer
+ setStorage('selected-layer-id', layer.id)
+
+ if (!event) {
+ event = layer.events.length ? layer.events[layer.events.length - 1] : null
+ }
+ inspectedEvent.value = event
+ selectedEvent.value = event
+
+ router.push({
+ query: {
+ ...router.currentRoute.value.query,
+ tabId: 'all',
+ },
+ })
+ }
+
+ return {
+ layers,
+ allLayers,
+ vScroll: computed({
+ get: () => vScrollPerApp.value[currentAppId.value] || 0,
+ set: (value: number) => {
+ vScrollPerApp.value[currentAppId.value] = value
+ },
+ }),
+ isLayerHidden,
+ setLayerHidden,
+ hoverLayerId,
+ selectedLayer: computed(() => selectedLayer.value),
+ selectLayer,
+ }
+}
+
+export async function fetchLayers() {
+ await waitForAppSelect()
+ getBridge().send(BridgeEvents.TO_BACK_TIMELINE_LAYER_LIST, {})
+}
+
+export function getGroupsAroundPosition(layer: Layer, startPosition: number, endPosition: number): EventGroup[] {
+ const result = new Set()
+ let key = Math.round(startPosition / 100_000)
+ const endKey = Math.round(endPosition / 100_000)
+ while (key <= endKey) {
+ const groups = layer.groupPositionCache[key]
+ if (groups) {
+ for (const group of groups) {
+ result.add(group)
+ }
+ }
+ key++
+ }
+ return Array.from(result)
+}
+
+export function addGroupAroundPosition(layer: Layer, group: EventGroup, newPosition: number) {
+ let key = Math.round(group.lastEvent.time / 100_000)
+ const endKey = Math.round(newPosition / 100_000)
+
+ while (key <= endKey) {
+ let list = layer.groupPositionCache[key]
+ if (!list) {
+ list = layer.groupPositionCache[key] = []
+ }
+ if (!list.includes(group)) {
+ list.push(group)
+ }
+ key++
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/composable/markers.ts b/vue-devtools/packages/app-frontend/src/features/timeline/composable/markers.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f6ec4a1041007827769d114514e65a86365ef160
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/composable/markers.ts
@@ -0,0 +1,24 @@
+import { useCurrentApp } from '@front/features/apps'
+import { computed, watch } from 'vue'
+import { getBridge } from '@front/features/bridge'
+import { BridgeEvents } from '@vue-devtools/shared-utils'
+import { markersAllApps, markersPerApp } from './store'
+
+export function useMarkers() {
+ const { currentAppId } = useCurrentApp()
+ const currentAppMarkers = computed(() => markersAllApps.value.concat(markersPerApp.value[currentAppId.value] ?? []))
+
+ watch(currentAppId, () => {
+ loadMarkers()
+ }, {
+ immediate: true,
+ })
+
+ return {
+ currentAppMarkers,
+ }
+}
+
+function loadMarkers() {
+ getBridge().send(BridgeEvents.TO_BACK_TIMELINE_LOAD_MARKERS)
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/composable/reset.ts b/vue-devtools/packages/app-frontend/src/features/timeline/composable/reset.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8152f445402c07169c0579c9da91c7af4142e567
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/composable/reset.ts
@@ -0,0 +1,69 @@
+import { onUnmounted } from 'vue'
+import { BridgeEvents, getStorage } from '@vue-devtools/shared-utils'
+import { getBridge } from '@front/features/bridge'
+import {
+ endTime,
+ hiddenLayersPerApp,
+ hoverLayerId,
+ inspectedEvent,
+ inspectedEventData,
+ inspectedEventPendingId,
+ layersPerApp,
+ maxTime,
+ minTime,
+ screenshots,
+ selectedEvent,
+ selectedLayer,
+ startTime,
+ timelineIsEmpty,
+ vScrollPerApp,
+} from './store'
+import { fetchLayers } from './layers'
+
+type ResetCb = () => void
+
+const resetCbs: ResetCb[] = []
+
+export function resetTimeline(sync = true) {
+ selectedLayer.value = null
+ selectedEvent.value = null
+ inspectedEvent.value = null
+ inspectedEventData.value = null
+ inspectedEventPendingId.value = null
+ layersPerApp.value = {}
+ vScrollPerApp.value = {}
+ hoverLayerId.value = null
+ timelineIsEmpty.value = true
+ screenshots.value = []
+
+ resetTime()
+
+ if (sync) {
+ getBridge().send(BridgeEvents.TO_BACK_TIMELINE_CLEAR)
+ }
+
+ // Layers
+ fetchLayers()
+ hiddenLayersPerApp.value = getStorage('hidden-layers', {})
+
+ for (const cb of resetCbs) {
+ cb()
+ }
+}
+
+export function resetTime() {
+ const now = 0
+ minTime.value = startTime.value = now - 1_000_000
+ maxTime.value = endTime.value = now
+}
+
+export function onTimelineReset(cb: ResetCb) {
+ onUnmounted(() => {
+ const index = resetCbs.indexOf(cb)
+ if (index !== -1) {
+ resetCbs.splice(index, 1)
+ }
+ })
+
+ resetCbs.push(cb)
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/composable/screenshot.ts b/vue-devtools/packages/app-frontend/src/features/timeline/composable/screenshot.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a4213caace0d52ab3f1aa164d9a513546705b58f
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/composable/screenshot.ts
@@ -0,0 +1,95 @@
+import { BridgeEvents, SharedData } from '@vue-devtools/shared-utils'
+import { useApps } from '@front/features/apps'
+import { useBridge } from '@front/features/bridge'
+import type { EventScreenshot, TimelineEvent } from './store'
+import { screenshots } from './store'
+
+let nextScreenshotId = 0
+
+export async function takeScreenshot(event: TimelineEvent) {
+ if (!SharedData.timelineScreenshots || event.layer.skipScreenshots) {
+ return
+ }
+
+ const time = Math.round(event.time / 100_000) * 100_000
+
+ const lastScreenshot = screenshots.value[screenshots.value.length - 1]
+
+ if (!lastScreenshot || lastScreenshot.time !== time) {
+ const screenshot: EventScreenshot = {
+ id: nextScreenshotId++,
+ time,
+ image: null,
+ events: [
+ event,
+ ],
+ }
+ event.screenshot = screenshot
+
+ // Screenshot
+ if (typeof browser !== 'undefined') {
+ browser.runtime.sendMessage({
+ action: 'vue-take-screenshot',
+ id: screenshot.id,
+ })
+ screenshots.value.push(screenshot)
+ }
+ else if (typeof chrome !== 'undefined' && chrome.tabs && typeof chrome.tabs.captureVisibleTab === 'function') {
+ chrome.tabs.captureVisibleTab({
+ format: 'png',
+ }, (dataUrl) => {
+ screenshot.image = dataUrl
+
+ if (!dataUrl) {
+ event.screenshot = lastScreenshot
+ if (lastScreenshot) {
+ lastScreenshot.events.push(event)
+ }
+ }
+ else {
+ screenshots.value.push(screenshot)
+ }
+ })
+ }
+ }
+ else {
+ event.screenshot = lastScreenshot
+ if (lastScreenshot) {
+ lastScreenshot.events.push(event)
+ }
+ }
+}
+
+export const supportsScreenshot = typeof browser !== 'undefined' || (typeof chrome !== 'undefined' && !!chrome.tabs && typeof chrome.tabs.captureVisibleTab === 'function')
+
+if (typeof browser !== 'undefined' && browser.runtime.onMessage) {
+ browser.runtime.onMessage.addListener((req) => {
+ if (req.action === 'vue-screenshot-result') {
+ const screenshot = screenshots.value.find(s => s.id === req.id)
+ if (screenshot) {
+ screenshot.image = req.dataUrl
+ }
+ }
+ })
+}
+
+export function useScreenshots() {
+ const { bridge } = useBridge()
+ const { currentAppId } = useApps()
+
+ function showScreenshot(screenshot: EventScreenshot = null) {
+ bridge.send(BridgeEvents.TO_BACK_TIMELINE_SHOW_SCREENSHOT, {
+ screenshot: screenshot
+ ? {
+ ...screenshot,
+ events: screenshot.events.filter(event => event.appId === currentAppId.value).map(event => event.id),
+ }
+ : null,
+ })
+ }
+
+ return {
+ screenshots,
+ showScreenshot,
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/composable/setup.ts b/vue-devtools/packages/app-frontend/src/features/timeline/composable/setup.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a351d64d0cca38fd480d7ee1be40276b761f531d
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/composable/setup.ts
@@ -0,0 +1,145 @@
+import type { Bridge } from '@vue-devtools/shared-utils'
+import { BridgeEvents, parse } from '@vue-devtools/shared-utils'
+import { getApps } from '@front/features/apps'
+import type {
+ MarkerFromBackend,
+ TimelineEvent,
+ TimelineMarker,
+} from './store'
+import {
+ inspectedEvent,
+ inspectedEventData,
+ inspectedEventPendingId,
+ markersAllApps,
+ markersPerApp,
+} from './store'
+import { fetchLayers, getLayers, layerFactory } from './layers'
+import { addEvent } from './events'
+import { resetTimeline } from './reset'
+
+const pendingEvents: Record = {}
+
+export function setupTimelineBridgeEvents(bridge: Bridge) {
+ resetTimeline(false)
+
+ bridge.on(BridgeEvents.TO_FRONT_TIMELINE_EVENT, ({ appId, layerId, event }) => {
+ const appIds = appId === 'all' ? getApps().map(app => app.id) : [appId]
+ for (const appId of appIds) {
+ const layer = getLayers(appId).find(l => l.id === layerId)
+ if (!layer) {
+ // Layer not found
+ const pendingKey = `${appId}:${layerId}`
+ pendingEvents[pendingKey] = pendingEvents[pendingKey] ?? []
+ pendingEvents[pendingKey].push(event)
+ return
+ }
+
+ addEvent(appId, event, layer)
+ }
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_TIMELINE_LAYER_ADD, () => {
+ fetchLayers()
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_TIMELINE_LAYER_LIST, ({ layers }) => {
+ for (const layer of layers) {
+ const appIds = layer.appId != null ? [layer.appId] : getApps().map(app => app.id)
+ for (const appId of appIds) {
+ const existingLayers = getLayers(appId)
+ if (!existingLayers.some(l => l.id === layer.id)) {
+ existingLayers.push(layerFactory(layer))
+
+ // Add pending events
+ const pendingKey = `${appId}:${layer.id}`
+ if (pendingEvents[pendingKey] && pendingEvents[pendingKey].length) {
+ for (const event of pendingEvents[pendingKey]) {
+ addEvent(appId, event, getLayers(appId).find(l => l.id === layer.id))
+ }
+ pendingEvents[pendingKey] = []
+ }
+
+ // Load existing events that may not have been catched
+ bridge.send(BridgeEvents.TO_BACK_TIMELINE_LAYER_LOAD_EVENTS, { layerId: layer.id, appId })
+ }
+ }
+ }
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_TIMELINE_EVENT_DATA, ({ eventId, data }) => {
+ if (inspectedEvent.value) {
+ if (inspectedEvent.value.id === eventId) {
+ inspectedEventData.value = parse(data)
+
+ if (data === null) {
+ inspectedEvent.value = null
+ }
+ }
+ if (eventId === inspectedEventPendingId.value) {
+ inspectedEventPendingId.value = null
+ }
+ }
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_TIMELINE_LAYER_LOAD_EVENTS, ({ appId, layerId, events }) => {
+ const layer = getLayers(appId).find(l => l.id === layerId)
+ if (!layer) {
+ // Layer not found
+ const pendingKey = `${appId}:${layerId}`
+ pendingEvents[pendingKey] = pendingEvents[pendingKey] ?? []
+ pendingEvents[pendingKey].push(...events)
+ return
+ }
+
+ for (const event of events) {
+ addEvent(appId, event, layer)
+ }
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_TIMELINE_LOAD_MARKERS, ({ markers, appId }: { markers: MarkerFromBackend[], appId: string }) => {
+ const allList: TimelineMarker[] = []
+ const appList: TimelineMarker[] = []
+
+ for (const marker of markers) {
+ const result = {
+ ...marker,
+ x: 0,
+ }
+ if (marker.all) {
+ allList.push(result)
+ }
+ else {
+ appList.push(result)
+ }
+ }
+
+ markersAllApps.value = allList
+ markersPerApp.value[appId] = appList
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_TIMELINE_MARKER, ({ marker, appId }: { marker: MarkerFromBackend, appId: string }) => {
+ let targetList: TimelineMarker[]
+ if (marker.all) {
+ targetList = markersAllApps.value
+ }
+ else {
+ if (!markersPerApp.value[appId]) {
+ markersPerApp.value[appId] = []
+ }
+ targetList = markersPerApp.value[appId]
+ }
+
+ const result = {
+ ...marker,
+ x: 0,
+ }
+
+ const index = targetList.findIndex(m => m.id === marker.id)
+ if (index !== -1) {
+ targetList.splice(index, 1, result)
+ }
+ else {
+ targetList.push(result)
+ }
+ })
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/composable/store.ts b/vue-devtools/packages/app-frontend/src/features/timeline/composable/store.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4c75db89ee39c7854eade3cab714b576f278d1df
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/composable/store.ts
@@ -0,0 +1,107 @@
+import type { Ref } from 'vue'
+import { ref } from 'vue'
+import type { ID } from '@vue/devtools-api'
+import type * as PIXI from 'pixi.js-legacy'
+
+export interface TimelineEventFromBackend {
+ id: number
+ time: number
+ logType: 'default' | 'warning' | 'error'
+ groupId: ID
+ title: string
+ subtitle: string
+}
+
+export interface EventGroup {
+ id: ID
+ events: TimelineEvent[]
+ firstEvent: TimelineEvent
+ lastEvent: TimelineEvent
+ duration: number
+ nonReactiveDuration: number
+ y: number
+ oldSize?: number
+ oldSelected?: boolean
+}
+
+export interface EventScreenshot {
+ id: number
+ time: number
+ image: string
+ events: TimelineEvent[]
+}
+
+export interface TimelineEvent extends TimelineEventFromBackend {
+ layer: Layer
+ appId: string | 'all'
+ group: EventGroup
+ screenshot: EventScreenshot
+ container: PIXI.Container
+ g: PIXI.Graphics
+ groupG: PIXI.Graphics
+ groupT: PIXI.BitmapText
+ groupText: string
+ forcePositionUpdate?: boolean
+}
+
+export interface LayerFromBackend {
+ id: string
+ label: string
+ color: number
+ appId?: string
+ pluginId?: string
+ groupsOnly?: boolean
+ skipScreenshots?: boolean
+ ignoreNoDurationGroups?: boolean
+}
+
+export interface Layer extends LayerFromBackend {
+ events: TimelineEvent[]
+ eventsMap: Record
+ groups: EventGroup[]
+ groupsMap: Record
+ groupPositionCache: Record
+ height: number
+ newHeight: number
+ lastInspectedEvent: TimelineEvent
+ loaded: boolean
+}
+
+export interface MarkerFromBackend {
+ id: string
+ appId: string
+ all?: boolean
+ time: number
+ label: string
+ color: number
+}
+
+export interface TimelineMarker extends MarkerFromBackend {
+ x: number
+}
+
+export const startTime = ref(0)
+export const endTime = ref(0)
+export const minTime = ref(0)
+export const maxTime = ref(0)
+
+export const timelineIsEmpty = ref(true)
+
+export const cursorTime = ref(null)
+
+export const layersPerApp: Ref<{ [appId: string]: Layer[] }> = ref({})
+export const hiddenLayersPerApp: Ref<{ [appId: string]: Layer['id'][] }> = ref({})
+export const vScrollPerApp: Ref<{ [appId: string]: number }> = ref({})
+
+export const selectedEvent: Ref = ref(null)
+export const selectedLayer: Ref = ref(null)
+export const hoverLayerId: Ref = ref(null)
+
+export const inspectedEvent: Ref = ref(null)
+export const inspectedEventData = ref(null)
+export const inspectedEventPendingId: Ref = ref(null)
+
+export const screenshots: Ref = ref([])
+
+export const markersAllApps: Ref = ref([])
+export const markersPerApp: Ref<{ [appId: string]: TimelineMarker[] }> = ref({})
diff --git a/vue-devtools/packages/app-frontend/src/features/timeline/composable/time.ts b/vue-devtools/packages/app-frontend/src/features/timeline/composable/time.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c2fe2efb061f2fb5df187eceab3ac2a1dfed3a53
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/timeline/composable/time.ts
@@ -0,0 +1,22 @@
+import {
+ cursorTime,
+ endTime,
+ maxTime,
+ minTime,
+ startTime,
+} from './store'
+
+export function useTime() {
+ return {
+ startTime,
+ endTime,
+ minTime,
+ maxTime,
+ }
+}
+
+export function useCursor() {
+ return {
+ cursorTime,
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueButton.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueButton.vue
new file mode 100644
index 0000000000000000000000000000000000000000..32055cdfffaa2de97a78bb644846668a4eb2ec67
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueButton.vue
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueDisable.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueDisable.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e367c81383cc9367028685842a45c02b5c51e849
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueDisable.vue
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueDropdown.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueDropdown.vue
new file mode 100644
index 0000000000000000000000000000000000000000..76451363281482f612d17caf66ead68b3906d20f
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueDropdown.vue
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueDropdownButton.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueDropdownButton.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b0c329185156a589fa3fc2070e00a320516b1f02
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueDropdownButton.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueFormField.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueFormField.vue
new file mode 100644
index 0000000000000000000000000000000000000000..313a3bd3ea3002383156339a7011c2f46f34212a
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueFormField.vue
@@ -0,0 +1,94 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueGroup.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueGroup.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f003feae4d159dd69117174936126f54e36fcf4d
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueGroup.vue
@@ -0,0 +1,131 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueGroupButton.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueGroupButton.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0cbee14d37c205b980604377a9f499bcea445f40
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueGroupButton.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueIcon.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueIcon.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4255ac63f5428eb1b9a1afe3921d5bd1bd326470
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueIcon.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueInput.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueInput.vue
new file mode 100644
index 0000000000000000000000000000000000000000..8ddf8153d32924ac995ee3e0da8a5fd087fdbc9c
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueInput.vue
@@ -0,0 +1,445 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueLoadingBar.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueLoadingBar.vue
new file mode 100644
index 0000000000000000000000000000000000000000..5d1bfdff0c6e549e6cd4523106878144eb17f354
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueLoadingBar.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueLoadingIndicator.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueLoadingIndicator.vue
new file mode 100644
index 0000000000000000000000000000000000000000..751b25232500835a9efb281ddc836812aa6a3bef
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueLoadingIndicator.vue
@@ -0,0 +1,6 @@
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueModal.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueModal.vue
new file mode 100644
index 0000000000000000000000000000000000000000..ce1bd2d1de31942dd2a99f429e1c4214e410342b
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueModal.vue
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueSelect.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueSelect.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0d31a97b321e5ea223f7bb04429a90a0001b4fcc
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueSelect.vue
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueSelectButton.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueSelectButton.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c17af73a6675dac13c179722849786bdb97d47d1
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueSelectButton.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/VueSwitch.vue b/vue-devtools/packages/app-frontend/src/features/ui/components/VueSwitch.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1f0da92d98b189c046ab52dd2a1b84adc095ac42
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/VueSwitch.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/components/icons.ts b/vue-devtools/packages/app-frontend/src/features/ui/components/icons.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1dc9c5675c21a9f0ae1008e83f5d358fbec79753
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/components/icons.ts
@@ -0,0 +1,35 @@
+const icons = require.context(
+ '@akryum/md-icons-svg/svg/',
+ true,
+ /materialicons\/24px\.svg$/,
+)
+
+export default {
+ install() {
+ const sprites = ['']
+ let spriteIndex = 0
+ // Load all the SVG symbols
+ icons.keys().forEach((key, index) => {
+ let result = icons(key)
+ const [, iconName] = /(\w+)\/materialicons/.exec(key)
+ // eslint-disable-next-line regexp/no-super-linear-backtracking
+ const [, content] = /(.*)<\/svg>/.exec(result)
+ result = ``
+ sprites[spriteIndex] += result
+ if ((index + 1) % 40 === 0) {
+ sprites.push('')
+ spriteIndex++
+ }
+ })
+ for (const html of sprites) {
+ const iconsWrapper = document.createElement('div')
+ iconsWrapper.style.display = 'none'
+ iconsWrapper.innerHTML = html
+ document.body.insertBefore(iconsWrapper, document.body.firstChild)
+ }
+ },
+}
+
+export function generateHtmlIcon(icon: string) {
+ return ``
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/composables/useDisableScroll.ts b/vue-devtools/packages/app-frontend/src/features/ui/composables/useDisableScroll.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0304a6cbd014aa4f2b8d75d5d5d10e9351fe7b45
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/composables/useDisableScroll.ts
@@ -0,0 +1,30 @@
+import { onBeforeUnmount, onMounted } from 'vue'
+
+let count = 0
+
+function getScrollingElements() {
+ return document.querySelectorAll('.vue-ui-disable-scroll, body')
+}
+
+function updateScroll() {
+ if (count === 0) {
+ getScrollingElements().forEach(el =>
+ el.classList.remove('vue-ui-no-scroll'),
+ )
+ }
+ else if (count === 1) {
+ getScrollingElements().forEach(el => el.classList.add('vue-ui-no-scroll'))
+ }
+}
+
+export function useDisableScroll() {
+ onMounted(() => {
+ count++
+ updateScroll()
+ })
+
+ onBeforeUnmount(() => {
+ count--
+ updateScroll()
+ })
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/composables/useDisabled.ts b/vue-devtools/packages/app-frontend/src/features/ui/composables/useDisabled.ts
new file mode 100644
index 0000000000000000000000000000000000000000..072e9353945801424c1493f0869c994e3d7a3ce5
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/composables/useDisabled.ts
@@ -0,0 +1,36 @@
+/**
+ * (Use with the DisabledChild mixin)
+ * Allow disabling an entire tree of components implementing the DisabledChild mixin.
+ */
+
+import { computed, inject, provide, reactive, watch } from 'vue'
+
+export function useDisabledParent(props: { disabled?: boolean }) {
+ const injectedDisableData = reactive({
+ value: props.disabled || false,
+ })
+
+ provide('VueDisableMixin', {
+ data: injectedDisableData,
+ })
+
+ watch(
+ () => props.disabled,
+ (value, oldValue) => {
+ if (value !== oldValue) {
+ injectedDisableData.value = value
+ }
+ },
+ )
+}
+
+export function useDisabledChild(props: { disabled?: boolean }) {
+ const injectDisable = inject<{ data: { value: boolean } } | undefined>(
+ 'VueDisableMixin',
+ null,
+ )
+
+ return {
+ finalDisabled: computed(() => props.disabled || (injectDisable && injectDisable.data.value)),
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/features/ui/index.ts b/vue-devtools/packages/app-frontend/src/features/ui/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e791e14d151a2df3afa294cf3e8457ba9c32d867
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/ui/index.ts
@@ -0,0 +1,60 @@
+import type { Plugin } from 'vue'
+import FloatingVue from 'floating-vue'
+import VueIcons from './components/icons'
+import VueDisable from './components/VueDisable.vue'
+import VueButton from './components/VueButton.vue'
+import VueDropdown from './components/VueDropdown.vue'
+import VueDropdownButton from './components/VueDropdownButton.vue'
+import VueFormField from './components/VueFormField.vue'
+import VueLoadingIndicator from './components/VueLoadingIndicator.vue'
+import VueGroup from './components/VueGroup.vue'
+import VueGroupButton from './components/VueGroupButton.vue'
+import VueIcon from './components/VueIcon.vue'
+import VueInput from './components/VueInput.vue'
+import VueLoadingBar from './components/VueLoadingBar.vue'
+import VueSwitch from './components/VueSwitch.vue'
+import VueSelect from './components/VueSelect.vue'
+import VueSelectButton from './components/VueSelectButton.vue'
+import VueModal from './components/VueModal.vue'
+import 'floating-vue/dist/style.css'
+
+export { generateHtmlIcon } from './components/icons'
+
+const ui: Plugin = {
+ install(app) {
+ app.use(VueIcons)
+ app.component('VueButton', VueButton)
+ app.component('VueDisable', VueDisable)
+ app.component('VueDropdown', VueDropdown)
+ app.component('VueFormField', VueFormField)
+ app.component('VueDropdownButton', VueDropdownButton)
+ app.component('VueLoadingIndicator', VueLoadingIndicator)
+ app.component('VueGroup', VueGroup)
+ app.component('VueGroupButton', VueGroupButton)
+ app.component('VueIcon', VueIcon)
+ app.component('VueInput', VueInput)
+ app.component('VueLoadingBar', VueLoadingBar)
+ app.component('VueSwitch', VueSwitch)
+ app.component('VueSelect', VueSelect)
+ app.component('VueSelectButton', VueSelectButton)
+ app.component('VueModal', VueModal)
+
+ app.use(FloatingVue, {
+ container: 'body',
+ instantMove: true,
+ themes: {
+ tooltip: {
+ delay: {
+ show: 1000,
+ hide: 800,
+ },
+ },
+ dropdown: {
+ handleResize: false,
+ },
+ },
+ })
+ },
+}
+
+export default ui
diff --git a/vue-devtools/packages/app-frontend/src/features/welcome/WelcomeSlideshow.vue b/vue-devtools/packages/app-frontend/src/features/welcome/WelcomeSlideshow.vue
new file mode 100644
index 0000000000000000000000000000000000000000..06e6005320e4bd146922ada295b9ab072b46c646
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/features/welcome/WelcomeSlideshow.vue
@@ -0,0 +1,267 @@
+
+
+
+
+
+
+
+
+
+ Welcome to the Vue devtools!
+
+
+
+
+ Let's take a little tour
+
+
+ The devtools were entirely rewritten with the release of Vue 3.
+
+
+
+ Its new architecture allows better support of different versions of Vue, as well as integration of third-party libraries (more on that later!).
+
+
+
+ It's packed with changes big and small, so here is an overview of what's new!
+
+
+
+
+
+
+
+ You might notice that the navigation is different. The devtools now has two main tabs:
+
+
+
+ - the Inspector to display debugging information in a structured way (for example inspecting a component),
+ - the Timeline to track different kinds of data over time such as events.
+
+
+
+
+ The Inspector
+
+
+ Here you can select components and inspect their state.
+
+
+
+
+
+
+
+ To access settings, use the new "3 dots" menu in the top right corner.
+
+
+
+
+
+
+
+ Any Vue plugin and library can now integrate with the devtools via its Plugin API.
+
+
+
+ For example, they can add their own custom inspectors:
+
+
+
+
+
+
+ The Timeline
+
+
+ Here you can see the events coming from your application in real-time. It includes mouse and keyboard events, component events, performance flamecharts...
+
+
+
+
+
+
+
+ You can zoom and pan the timeline, or click on events to see more information.
+
+
+
+
+
+
+
+ Using the Devtools Plugin API, third-party libraries can also add layers and events to the Timeline.
+
+
+
+
+
+
+
+ On the left side of the top bar, you can find a new App Selector. The devtools are now scoped to a specific selected app and can even inspect apps inside iframes!
+
+
+
+
+
+
+
+
+
+ That's it!
+
+
+
+ We hope that you will enjoy the new Vue devtools.
+
+
+
+ In case something doesn't work with your project, you can use the Legacy version and report an issue.
+
+
+
+
+
+
+
+
+ Skip
+
+
+
+ Previous
+
+
+ Next
+
+
+ Continue
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/app-frontend/src/index.ts b/vue-devtools/packages/app-frontend/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..13f01e9c1b32e625301c396fa75f122556c8c058
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/index.ts
@@ -0,0 +1,26 @@
+import './assets/style/index.styl'
+import './assets/style/index.postcss'
+
+import type { Shell } from '@vue-devtools/shared-utils'
+import { initStorage } from '@vue-devtools/shared-utils'
+import { connectApp, createApp } from './app'
+import { setAppConnected } from './features/connection'
+import { getBridge } from './features/bridge'
+
+export { setAppConnected } from './features/connection'
+
+/**
+ * Create the main devtools app. Expects to be called with a shell interface
+ * which implements a connect method.
+ */
+export async function initDevTools(shell: Shell) {
+ await initStorage()
+ const app = createApp()
+ app.mount('#app')
+ connectApp(app, shell)
+ shell.onReload(() => {
+ setAppConnected(false, true, true)
+ getBridge()?.removeAllListeners()
+ connectApp(app, shell)
+ })
+}
diff --git a/vue-devtools/packages/app-frontend/src/locales/en.js b/vue-devtools/packages/app-frontend/src/locales/en.js
new file mode 100644
index 0000000000000000000000000000000000000000..cff0ebef027dc6a3ff5365b9e88ae97aadb27949
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/locales/en.js
@@ -0,0 +1,107 @@
+export default {
+ App: {
+ components: {
+ tooltip: '[[{{keys.ctrl}}]] + [[1]] Switch to Components',
+ },
+ events: {
+ tooltip: '[[{{keys.ctrl}}]] + [[3]] Switch to Events',
+ },
+ refresh: {
+ tooltip: '[[{{keys.ctrl}}]] + [[{{keys.alt}}]] + [[R]] Force Refresh',
+ },
+ routing: {
+ tooltip: '[[{{keys.ctrl}}]] + [[4]] Switch to Routing',
+ },
+ perf: {
+ tooltip: '[[{{keys.ctrl}}]] + [[5]] Switch to Performance',
+ },
+ settings: {
+ tooltip: '[[{{keys.ctrl}}]] + [[6]] Switch to Settings',
+ },
+ vuex: {
+ tooltip: '[[{{keys.ctrl}}]] + [[2]] Switch to Vuex',
+ },
+ },
+ StateInspector: {
+ dataType: {
+ tooltip: '[[{{keys.shift}}]] + <>: Expand/Collapse All
Using this shortcut will override the default toggled state and save it for next time.
',
+ },
+ filter: {
+ tooltip: '[[{{keys.alt}}]] + [[D]] Filter state by name',
+ },
+ },
+ DataField: {
+ edit: {
+ cancel: {
+ tooltip: '[[{{keys.esc}}]] Cancel',
+ },
+ submit: {
+ tooltip: '[[{{keys.enter}}]] Submit change',
+ },
+ },
+ contextMenu: {
+ copyValue: 'Copy Value',
+ copyPath: 'Copy Path',
+ },
+ quickEdit: {
+ number: {
+ tooltip: `Quick Edit
+ [[{{keys.ctrl}}]] + <>: {{operator}}5
+ [[{{keys.shift}}]] + <>: {{operator}}10
+ [[{{keys.alt}}]] + <>: {{operator}}100`,
+ },
+ },
+ },
+ ComponentTree: {
+ select: {
+ tooltip: '[[{{keys.alt}}]] + [[S]] Select component in the page',
+ },
+ filter: {
+ tooltip: '[[{{keys.alt}}]] + [[F]] Filter components by name',
+ },
+ refresh: {
+ tooltip: '[[{{keys.ctrl}}]] + [[{{keys.alt}}]] + [[R]] Force refresh',
+ },
+ },
+ ComponentInstance: {
+ consoleId: {
+ tooltip: 'Available as {{id}} in the console.',
+ },
+ },
+ ComponentInspector: {
+ openInEditor: {
+ tooltip: 'Open <>{{file}} in editor',
+ },
+ },
+ EventsHistory: {
+ filter: {
+ tooltip: '[[{{keys.ctrl}}]] + [[F]] To filter on components, type <> <MyComponent> or just <> <mycomp.',
+ },
+ clear: {
+ tooltip: '[[{{keys.ctrl}}]] + [[{{keys.del}}]] Clear Log',
+ },
+ startRecording: {
+ tooltip: '[[R]] Start recording',
+ },
+ stopRecording: {
+ tooltip: '[[R]] Stop recording',
+ },
+ },
+ VuexHistory: {
+ filter: {
+ tooltip: '[[{{keys.ctrl}}]] + [[F]] Filter mutations',
+ },
+ commitAll: {
+ tooltip: '[[{{keys.ctrl}}]] + [[{{keys.enter}}]] Commit all',
+ },
+ revertAll: {
+ tooltip: '[[{{keys.ctrl}}]] + [[{{keys.del}}]] Revert all',
+ },
+ startRecording: {
+ tooltip: '[[R]] Start recording',
+ },
+ stopRecording: {
+ tooltip: '[[R]] Stop recording',
+ },
+ },
+}
diff --git a/vue-devtools/packages/app-frontend/src/mixins/data-field-edit.js b/vue-devtools/packages/app-frontend/src/mixins/data-field-edit.js
new file mode 100644
index 0000000000000000000000000000000000000000..25c116be7c6ccc9db1091bb93c78e47b56004ec1
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/mixins/data-field-edit.js
@@ -0,0 +1,296 @@
+import {
+ SPECIAL_TOKENS,
+ UNDEFINED,
+ parse,
+} from '@vue-devtools/shared-utils'
+
+let currentEditedField = null
+
+function numberQuickEditMod(event) {
+ let mod = 1
+ if (event.ctrlKey || event.metaKey) {
+ mod *= 5
+ }
+ if (event.shiftKey) {
+ mod *= 10
+ }
+ if (event.altKey) {
+ mod *= 100
+ }
+ return mod
+}
+
+export default {
+ inject: {
+ InspectorInjection: {
+ default: null,
+ },
+ },
+
+ props: {
+ editable: {
+ type: Boolean,
+ default: false,
+ },
+ removable: {
+ type: Boolean,
+ default: false,
+ },
+ renamable: {
+ type: Boolean,
+ default: false,
+ },
+ },
+
+ data() {
+ return {
+ editing: false,
+ editedValue: null,
+ editedKey: null,
+ addingValue: false,
+ newField: null,
+ }
+ },
+
+ computed: {
+ cssClass() {
+ return {
+ editing: this.editing,
+ }
+ },
+
+ isEditable() {
+ if (this.InspectorInjection && !this.InspectorInjection.editable) {
+ return false
+ }
+ return this.editable
+ && !this.fieldOptions.abstract
+ && !this.fieldOptions.readOnly
+ && (
+ typeof this.field.key !== 'string'
+ || this.field.key.charAt(0) !== '$'
+ )
+ },
+
+ isValueEditable() {
+ const type = this.interpretedValueType
+ const customType = this.customField?.type
+
+ return this.isEditable
+ && (
+ type === 'null'
+ || type === 'literal'
+ || type === 'string'
+ || type === 'array'
+ || type === 'plain-object'
+ || customType === 'bigint'
+ || customType === 'date'
+ )
+ },
+
+ customField() {
+ return this.field.value?._custom
+ },
+
+ inputType() {
+ if (this.customField?.type === 'date') {
+ return 'datetime-local'
+ }
+ return 'text'
+ },
+
+ isSubfieldsEditable() {
+ return this.isEditable && (this.interpretedValueType === 'array' || this.interpretedValueType === 'plain-object')
+ },
+
+ valueValid() {
+ try {
+ if (this.customField?.skipSerialize) {
+ return true
+ }
+ parse(this.transformSpecialTokens(this.editedValue, false))
+ return true
+ }
+ catch (e) {
+ return false
+ }
+ },
+
+ duplicateKey() {
+ return this.parentField && Object.prototype.hasOwnProperty.call(this.parentField.value, this.editedKey)
+ },
+
+ keyValid() {
+ return this.editedKey && (this.editedKey === this.field.key || !this.duplicateKey)
+ },
+
+ editValid() {
+ return this.valueValid && (!this.renamable || this.keyValid)
+ },
+
+ quickEdits() {
+ if (this.isValueEditable) {
+ const value = this.field.value
+ const type = typeof value
+ if (type === 'boolean') {
+ return [
+ {
+ icon: value ? 'check_box' : 'check_box_outline_blank',
+ newValue: !value,
+ },
+ ]
+ }
+ else if (type === 'number') {
+ return [
+ {
+ icon: 'remove',
+ class: 'big',
+ title: this.quickEditNumberTooltip('-'),
+ newValue: event => value - numberQuickEditMod(event),
+ },
+ {
+ icon: 'add',
+ class: 'big',
+ title: this.quickEditNumberTooltip('+'),
+ newValue: event => value + numberQuickEditMod(event),
+ },
+ ]
+ }
+ }
+ return null
+ },
+ },
+
+ methods: {
+ openEdit(focusKey = false) {
+ if (this.isValueEditable) {
+ if (currentEditedField && currentEditedField !== this) {
+ currentEditedField.cancelEdit()
+ }
+ let valueToEdit = this.field.value
+ // Edit custom value (we don't want to edit the whole custom value data object)
+ if (this.valueType === 'custom') {
+ valueToEdit = valueToEdit._custom.value
+ }
+ if (this.customField?.skipSerialize) {
+ this.editedValue = valueToEdit
+ }
+ else {
+ this.editedValue = this.transformSpecialTokens(JSON.stringify(valueToEdit), true)
+ }
+
+ this.editedKey = this.field.key
+ this.editing = true
+ // eslint-disable-next-line ts/no-this-alias
+ currentEditedField = this
+ this.$nextTick(() => {
+ const el = this.$refs[focusKey && this.renamable ? 'keyInput' : 'editInput']
+ try {
+ el.focus()
+ // Will cause DOMEException on the datetime-local input.
+ el.setSelectionRange(0, el.value.length)
+ }
+ catch {}
+ })
+ }
+ },
+
+ cancelEdit() {
+ this.editing = false
+ this.$emit('cancel-edit')
+ currentEditedField = null
+ },
+
+ submitEdit() {
+ if (this.editValid) {
+ this.editing = false
+ let value = this.customField?.skipSerialize ? this.editedValue : this.transformSpecialTokens(this.editedValue, false)
+ // We need to send the entire custom value data object
+ if (this.valueType === 'custom') {
+ value = JSON.stringify({
+ _custom: {
+ ...this.customField,
+ value: this.customField?.skipSerialize ? value : JSON.parse(value), // Input
+ },
+ })
+ }
+ const newKey = this.editedKey !== this.field.key ? this.editedKey : undefined
+ this.sendEdit({ value, newKey })
+ this.$emit('submit-edit')
+ }
+ },
+
+ sendEdit(payload) {
+ this.$emit('edit-state', this.path, payload)
+ },
+
+ transformSpecialTokens(str, display) {
+ if (str) {
+ Object.keys(SPECIAL_TOKENS).forEach((key) => {
+ const value = JSON.stringify(SPECIAL_TOKENS[key])
+ let search
+ let replace
+ if (display) {
+ search = value
+ replace = key
+ }
+ else {
+ search = key
+ replace = value
+ }
+ str = str.replace(new RegExp(search, 'g'), replace)
+ })
+ }
+ return str
+ },
+
+ quickEdit(info, event) {
+ let newValue
+ if (typeof info.newValue === 'function') {
+ newValue = info.newValue(event)
+ }
+ else {
+ newValue = info.newValue
+ }
+ this.sendEdit({ value: JSON.stringify(newValue) })
+ },
+
+ removeField() {
+ this.sendEdit({ remove: true })
+ },
+
+ addNewValue() {
+ let key
+ if (this.interpretedValueType === 'array') {
+ key = this.field.value.length
+ }
+ else if (this.interpretedValueType === 'plain-object') {
+ let i = 1
+ // eslint-disable-next-line no-cond-assign
+ while (Object.prototype.hasOwnProperty.call(this.field.value, key = `prop${i}`)) {
+ i++
+ }
+ }
+ this.newField = { key, value: UNDEFINED }
+ this.expanded = true
+ this.addingValue = true
+ this.$nextTick(() => {
+ this.$refs.newField.openEdit(true)
+ })
+ },
+
+ containsEdition() {
+ return currentEditedField && currentEditedField.path.indexOf(this.path) === 0
+ },
+
+ cancelCurrentEdition() {
+ this.containsEdition() && currentEditedField.cancelEdit()
+ },
+
+ quickEditNumberTooltip(operator) {
+ return this.$t('DataField.quickEdit.number.tooltip', {
+ operator,
+ })
+ },
+ },
+}
diff --git a/vue-devtools/packages/app-frontend/src/mixins/entry-list.ts b/vue-devtools/packages/app-frontend/src/mixins/entry-list.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d56a4f9635d82682f2a57b8baa40749d2afac5bd
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/mixins/entry-list.ts
@@ -0,0 +1,62 @@
+/* eslint-disable eslint-comments/no-unlimited-disable */
+/* eslint-disable */
+// @ts-nocheck (Unused file)
+
+import { defineComponent } from 'vue'
+import debounce from 'lodash/debounce'
+
+export default function ({
+ indexOffset = 0,
+} = {}) {
+ // @vue/component
+ return defineComponent({
+ watch: {
+ inspectedIndex: 'refreshScrollToInspected',
+ },
+
+ mounted() {
+ this.refreshScrollToInspected()
+ },
+
+ activated() {
+ this.refreshScrollToInspected()
+ },
+
+ methods: {
+ refreshScrollToInspected() {
+ if (this.inspectedIndex) { this.scrollIntoInspected(this.inspectedIndex as number) }
+ },
+
+ scrollIntoInspected: debounce(async function (index) {
+ index += indexOffset
+ // Wait for defer frames (time-slicing)
+ for (let f = 0; f < 2; f++) {
+ await waitForFrame()
+ }
+ const scroller = this.$globalRefs.leftRecycleList || this.$globalRefs.leftScroll
+ if (!scroller) {
+ this.scrollIntoInspected(index)
+ return
+ }
+ const parentHeight = scroller.offsetHeight
+ const height = this.highDensity ? 22 : 34
+ const top = index * height
+ const scrollTop = scroller.scrollTop
+ if (top < scrollTop) {
+ scroller.scrollTop = top
+ }
+ else if (top + height > scrollTop + parentHeight) {
+ scroller.scrollTop = top + height - parentHeight
+ }
+ } as (this: any, index: number) => Promise, 200, {
+ leading: true,
+ }),
+ },
+ })
+}
+
+function waitForFrame() {
+ return new Promise((resolve) => {
+ requestAnimationFrame(resolve)
+ })
+}
diff --git a/vue-devtools/packages/app-frontend/src/mixins/keyboard.ts b/vue-devtools/packages/app-frontend/src/mixins/keyboard.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fd72a818a9f2e0f76499e463270317a606f8f270
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/mixins/keyboard.ts
@@ -0,0 +1,70 @@
+import { defineComponent } from 'vue'
+
+export const LEFT = 'ArrowLeft'
+export const UP = 'ArrowUp'
+export const RIGHT = 'ArrowRight'
+export const DOWN = 'ArrowDown'
+export const ENTER = 'Enter'
+export const DEL = 'Delete'
+export const BACKSPACE = 'Backspace'
+
+const activeInstances = []
+
+function processEvent(event, type) {
+ if (
+ event.target.tagName === 'INPUT'
+ || event.target.tagName === 'TEXTAREA'
+ ) {
+ return
+ }
+ const modifiers: string[] = []
+ if (event.ctrlKey || event.metaKey) {
+ modifiers.push('ctrl')
+ }
+ if (event.shiftKey) {
+ modifiers.push('shift')
+ }
+ if (event.altKey) {
+ modifiers.push('alt')
+ }
+ const info = {
+ key: event.key,
+ code: event.code,
+ modifiers: modifiers.join('+'),
+ }
+ let result = true
+ activeInstances.forEach((opt) => {
+ if (opt[type]) {
+ const r = opt[type].call(opt.vm, info)
+ if (r === false) {
+ result = false
+ }
+ }
+ })
+ if (!result) {
+ event.preventDefault()
+ }
+}
+
+document.addEventListener('keydown', (event) => {
+ processEvent(event, 'onKeyDown')
+})
+
+export default function (options) {
+ return defineComponent({
+ mounted() {
+ activeInstances.push({
+ vm: this,
+ ...options,
+ })
+ },
+ unmounted() {
+ const i = activeInstances.findIndex(
+ o => o.vm === this,
+ )
+ if (i >= 0) {
+ activeInstances.splice(i, 1)
+ }
+ },
+ })
+}
diff --git a/vue-devtools/packages/app-frontend/src/plugins/global-refs.ts b/vue-devtools/packages/app-frontend/src/plugins/global-refs.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2a5ab6617443193f0451086e2ca44389c0bfdccf
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/plugins/global-refs.ts
@@ -0,0 +1,19 @@
+import type { App } from 'vue'
+
+interface Options {
+ refs: { [key: string]: any }
+}
+
+export default {
+ install(app: App, options: Options) {
+ const { refs } = options
+ const wrapper = {}
+ Object.keys(refs).forEach((key) => {
+ const get = refs[key]
+ Object.defineProperty(wrapper, key, {
+ get,
+ })
+ })
+ app.config.globalProperties.$globalRefs = wrapper
+ },
+}
diff --git a/vue-devtools/packages/app-frontend/src/plugins/i18n.ts b/vue-devtools/packages/app-frontend/src/plugins/i18n.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7fb0c0b9588c5094fbc76015c6fc9da34d8ecb7b
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/plugins/i18n.ts
@@ -0,0 +1,38 @@
+import { simpleGet } from '@vue-devtools/shared-utils'
+import type { Plugin } from 'vue'
+
+const reg = /\{\{\s*([\w.-]+)\s*\}\}/g
+
+interface StringMap { [key: string]: string | StringMap }
+interface ValuesMap { [key: string]: any }
+type Replacer = (text: string) => string
+
+let strings: StringMap
+let defaultValues: ValuesMap
+let replacer: Replacer
+
+export function translate(path: string | string[], values: ValuesMap = {}) {
+ values = Object.assign({}, defaultValues, values)
+ let text = simpleGet(strings, path)
+ text = text.replace(reg, (substring, matched) => {
+ const value = simpleGet(values, matched)
+ return typeof value !== 'undefined' ? value : substring
+ })
+ replacer && (text = replacer(text))
+ return text
+}
+
+interface Options {
+ strings: StringMap
+ defaultValues: ValuesMap
+ replacer: Replacer
+}
+
+export default {
+ install(app, options: Options) {
+ strings = options.strings || {}
+ defaultValues = options.defaultValues || {}
+ replacer = options.replacer
+ app.config.globalProperties.$t = translate
+ },
+} as Plugin
diff --git a/vue-devtools/packages/app-frontend/src/plugins/index.ts b/vue-devtools/packages/app-frontend/src/plugins/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cc8c0358fd362299f7cc309ab0df0231947fe76c
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/plugins/index.ts
@@ -0,0 +1,53 @@
+import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
+import 'vue-resize/dist/vue-resize.css'
+
+import type { App } from 'vue'
+import VueVirtualScroller from 'vue-virtual-scroller'
+import { keys } from '@vue-devtools/shared-utils'
+import VueSafeTeleport from 'vue-safe-teleport'
+import VueResize from 'vue-resize'
+import VueUi, { generateHtmlIcon } from '../features/ui'
+import VI18n from './i18n'
+import Responsive from './responsive'
+import GlobalRefs from './global-refs'
+
+export function setupPlugins(app: App) {
+ app.use(VueSafeTeleport)
+ app.use(VueUi)
+ app.use(VueResize)
+ app.use(VueVirtualScroller)
+
+ const currentLocale = 'en'
+ const locales = require.context('../locales')
+ const replacers = [
+ { reg: //g, replace: '' },
+ { reg: //g, replace: '' },
+ { reg: /<\/(input|mono)>/g, replace: '' },
+ { reg: /\[\[(\S+)\]\]/g, replace: '$1' },
+ { reg: /<<(\S+)>>/g, replace: (_, p1) => generateHtmlIcon(p1) as string },
+ ]
+
+ app.use(VI18n, {
+ strings: locales(`./${currentLocale}`).default,
+ defaultValues: {
+ keys,
+ },
+ replacer: (text: string) => {
+ for (const replacer of replacers) {
+ // @ts-expect-error meow
+ text = text.replace(replacer.reg, replacer.replace)
+ }
+ return text
+ },
+ })
+
+ app.use(Responsive)
+
+ app.use(GlobalRefs, {
+ refs: {
+ leftScroll: () => document.querySelector('.left .scroll'),
+ leftRecycleList: () => document.querySelector('.left .vue-recycle-scroller'),
+ rightScroll: () => document.querySelector('.right .scroll'),
+ },
+ })
+}
diff --git a/vue-devtools/packages/app-frontend/src/plugins/responsive.ts b/vue-devtools/packages/app-frontend/src/plugins/responsive.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5bc472b734cbcd32b69177fcd2d5017e74890c7f
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/plugins/responsive.ts
@@ -0,0 +1,44 @@
+import type { ComputedRef, Plugin, Ref } from 'vue'
+import { computed, inject, reactive, toRefs } from 'vue'
+
+export interface Responsive {
+ wide: ComputedRef
+ tall: ComputedRef
+ width: Ref
+ height: Ref
+}
+
+const responsiveKey = Symbol('responsive')
+
+export default {
+ install(app) {
+ function buildResponsive() {
+ const data = reactive({
+ width: window.innerWidth,
+ height: window.innerHeight,
+ })
+
+ const wide = computed(() => data.width >= 1050)
+ const tall = computed(() => data.height >= 350)
+
+ return {
+ ...toRefs(data),
+ wide,
+ tall,
+ }
+ }
+
+ const responsive = buildResponsive()
+
+ app.config.globalProperties.$responsive = responsive
+
+ app.provide(responsiveKey, responsive)
+
+ window.addEventListener('resize', () => {
+ responsive.width.value = window.innerWidth
+ responsive.height.value = window.innerHeight
+ })
+ },
+} as Plugin
+
+export const useResponsive = () => inject(responsiveKey)
diff --git a/vue-devtools/packages/app-frontend/src/router.ts b/vue-devtools/packages/app-frontend/src/router.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3832c048c95257bae3b942602b013d339b1e4dd9
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/router.ts
@@ -0,0 +1,109 @@
+import type { RouteLocationNormalized, RouteRecordRaw } from 'vue-router'
+import { createRouter, createWebHashHistory } from 'vue-router'
+import { BuiltinTabs, getStorage, setStorage } from '@vue-devtools/shared-utils'
+import ComponentsInspector from './features/components/ComponentsInspector.vue'
+import CustomInspector from './features/inspector/custom/CustomInspector.vue'
+import Timeline from './features/timeline/Timeline.vue'
+import Plugins from './features/plugin/Plugins.vue'
+import PluginHome from './features/plugin/PluginHome.vue'
+import PluginDetails from './features/plugin/PluginDetails.vue'
+import GlobalSettings from './features/settings/GlobalSettings.vue'
+
+const routes: RouteRecordRaw[] = [
+ {
+ path: '/',
+ redirect: {
+ // An error will be thrown if param id is not provided, provide a default value to avoid this.
+ // Ref: https://github.com/vuejs/router/issues/845
+ path: '/app/init/inspector/components',
+ },
+ },
+ {
+ path: '/app/:appId',
+ children: [
+ {
+ path: 'inspector',
+ name: 'inspector',
+ children: [
+ {
+ path: 'components/:componentId?',
+ name: 'inspector-components',
+ component: ComponentsInspector,
+ meta: {
+ tab: BuiltinTabs.COMPONENTS,
+ },
+ },
+ {
+ path: 'custom/:inspectorId',
+ name: 'custom-inspector',
+ component: CustomInspector,
+ meta: {
+ tab: (route: RouteLocationNormalized) => `custom-inspector:${route.params.inspectorId}`,
+ },
+ },
+ ],
+ },
+ {
+ path: 'timeline',
+ name: 'timeline',
+ component: Timeline,
+ meta: {
+ tab: BuiltinTabs.TIMELINE,
+ },
+ },
+ {
+ path: 'plugins',
+ component: Plugins,
+ meta: {
+ match: 'plugins',
+ tab: BuiltinTabs.PLUGINS,
+ },
+ children: [
+ {
+ path: '',
+ name: 'plugins',
+ component: PluginHome,
+ },
+ {
+ path: ':pluginId',
+ name: 'plugin-details',
+ component: PluginDetails,
+ props: true,
+ },
+ ],
+ },
+ {
+ path: 'settings',
+ name: 'global-settings',
+ component: GlobalSettings,
+ meta: {
+ tab: BuiltinTabs.SETTINGS,
+ },
+ },
+ ],
+ },
+ {
+ path: '/:pathMatch(.*)*',
+ redirect: '/',
+ },
+]
+
+const STORAGE_ROUTE = 'route'
+
+export function createRouterInstance() {
+ const router = createRouter({
+ history: createWebHashHistory('/'),
+ routes,
+ })
+
+ const previousRoute = getStorage(STORAGE_ROUTE)
+ if (previousRoute) {
+ router.push(previousRoute)
+ }
+
+ router.afterEach((to) => {
+ setStorage(STORAGE_ROUTE, to.fullPath)
+ })
+
+ return router
+}
diff --git a/vue-devtools/packages/app-frontend/src/shims-global.d.ts b/vue-devtools/packages/app-frontend/src/shims-global.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..57956fb0d686bcf4dfcdba38c75ab08b822b9df2
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/shims-global.d.ts
@@ -0,0 +1,2 @@
+// @TODO remove
+declare const browser: any
diff --git a/vue-devtools/packages/app-frontend/src/shims-vue.d.ts b/vue-devtools/packages/app-frontend/src/shims-vue.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0cf4e3d9a2ade0423032e89c50b96f9fb64b2d2c
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/shims-vue.d.ts
@@ -0,0 +1,5 @@
+declare module '*.vue' {
+ import type { defineComponent } from 'vue'
+
+ export default ReturnType
+}
diff --git a/vue-devtools/packages/app-frontend/src/types/vue.d.ts b/vue-devtools/packages/app-frontend/src/types/vue.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ae7fb8b150e62be405be7bb1687ede83b85b2cbd
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/types/vue.d.ts
@@ -0,0 +1,22 @@
+import type {
+ SharedData,
+ keys,
+} from '@vue-devtools/shared-utils'
+
+import type {
+ Responsive,
+} from '@front/plugins/responsive'
+
+declare module '@vue/runtime-core' {
+ interface ComponentCustomProperties {
+ $t: (string, values?: Record) => string
+ $responsive: Responsive
+ $shared: typeof SharedData
+ $isChrome: boolean
+ $isFirefox: boolean
+ $isWindows: boolean
+ $isMac: boolean
+ $isLinux: boolean
+ $keys: typeof keys
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/util/color.ts b/vue-devtools/packages/app-frontend/src/util/color.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7d39924f8d9668cfb0d7e5b71ed357a2a6024fa4
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/util/color.ts
@@ -0,0 +1,27 @@
+import tinycolor from 'tinycolor2'
+
+export function toStrHex(color: number) {
+ return color.toString(16).padStart(6, '0')
+}
+
+export function dimColor(color: number, dark: boolean, amount = 20) {
+ let c = tinycolor(toStrHex(color))
+ if (dark) {
+ c = c.darken(amount)
+ }
+ else {
+ c = c.lighten(amount)
+ }
+ return Number.parseInt(`0x${c.toHex()}`)
+}
+
+export function boostColor(color: number, dark: boolean, amount = 10) {
+ let c = tinycolor(toStrHex(color))
+ if (dark) {
+ c = c.lighten(amount)
+ }
+ else {
+ c = c.darken(amount)
+ }
+ return Number.parseInt(`0x${c.toHex()}`)
+}
diff --git a/vue-devtools/packages/app-frontend/src/util/defer.ts b/vue-devtools/packages/app-frontend/src/util/defer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..74daac853440a02ed3cfdd935e9a64608fc9e6ab
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/util/defer.ts
@@ -0,0 +1,30 @@
+import { onMounted, ref } from 'vue'
+
+export function useDefer(count = 10) {
+ const displayPriority = ref(0)
+
+ function step() {
+ requestAnimationFrame(() => {
+ displayPriority.value++
+ if (displayPriority.value < count) {
+ step()
+ }
+ })
+ }
+
+ function runDisplayPriority() {
+ step()
+ }
+
+ function defer(priority) {
+ return displayPriority.value >= priority
+ }
+
+ onMounted(() => {
+ runDisplayPriority()
+ })
+
+ return {
+ defer,
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/util/fonts.ts b/vue-devtools/packages/app-frontend/src/util/fonts.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e6e5550213c92a0220108699de592d8e8b002e93
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/util/fonts.ts
@@ -0,0 +1,49 @@
+import { ref } from 'vue'
+import * as PIXI from 'pixi.js-legacy'
+
+let installedFonts = false
+
+export async function installFonts() {
+ if (installedFonts) {
+ return
+ }
+
+ try {
+ await document.fonts.load('10px "Roboto Mono"')
+ }
+ catch (e) {
+ console.error(e)
+ }
+
+ PIXI.BitmapFont.from('roboto-black', {
+ fontFamily: 'Roboto Mono',
+ fontSize: 9,
+ fill: '#000000',
+ }, {
+ resolution: window.devicePixelRatio,
+ })
+
+ PIXI.BitmapFont.from('roboto-white', {
+ fontFamily: 'Roboto Mono',
+ fontSize: 9,
+ fill: '#ffffff',
+ }, {
+ resolution: window.devicePixelRatio,
+ })
+
+ installedFonts = true
+}
+
+export function useFonts() {
+ const loaded = ref(installedFonts)
+
+ async function _load() {
+ await installFonts()
+ loaded.value = true
+ }
+ _load()
+
+ return {
+ loaded,
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/util/format/index.ts b/vue-devtools/packages/app-frontend/src/util/format/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4f58395eccff7637f50d0b702fef56631d726f0f
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/util/format/index.ts
@@ -0,0 +1,2 @@
+export * from './time'
+export * from './value'
diff --git a/vue-devtools/packages/app-frontend/src/util/format/time.ts b/vue-devtools/packages/app-frontend/src/util/format/time.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d86fae40d572fc50417df2c2cf9b09086aa0ef31
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/util/format/time.ts
@@ -0,0 +1,6 @@
+export type TimeFormat = 'ms' | 'default'
+
+export function formatTime(timestamp: string | number | Date, format?: TimeFormat) {
+ const date = new Date(timestamp)
+ return `${date.toString().match(/\d\d:\d\d:\d\d/)[0]}${format === 'ms' ? `.${String(date.getMilliseconds()).padStart(3, '0')}` : ''}`
+}
diff --git a/vue-devtools/packages/app-frontend/src/util/format/value.ts b/vue-devtools/packages/app-frontend/src/util/format/value.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b6cf670053cc79b6560927e3fe203ea89344b689
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/util/format/value.ts
@@ -0,0 +1,102 @@
+import {
+ INFINITY,
+ NAN,
+ NEGATIVE_INFINITY,
+ UNDEFINED,
+ escape,
+ isPlainObject,
+ specialTokenToString,
+} from '@vue-devtools/shared-utils'
+
+const rawTypeRE = /^\[object (\w+)\]$/
+const specialTypeRE = /^\[native (\w+) (.*?)(?:<>[.\s]*)?\]$/
+
+export function valueType(value, raw = true) {
+ const type = typeof value
+ if (value == null || value === UNDEFINED) {
+ return 'null'
+ }
+ else if (
+ type === 'boolean'
+ || type === 'number'
+ || value === INFINITY
+ || value === NEGATIVE_INFINITY
+ || value === NAN
+ ) {
+ return 'literal'
+ }
+ else if (value?._custom) {
+ if ((raw || value._custom.display != null)) {
+ return 'custom'
+ }
+ else {
+ return valueType(value._custom.value)
+ }
+ }
+ else if (type === 'string') {
+ const typeMatch = specialTypeRE.exec(value)
+ if (typeMatch) {
+ const [, type] = typeMatch
+ return `native ${type}`
+ }
+ else {
+ return 'string'
+ }
+ }
+ else if (Array.isArray(value) || (value?._isArray)) {
+ return 'array'
+ }
+ else if (isPlainObject(value)) {
+ return 'plain-object'
+ }
+ else {
+ return 'unknown'
+ }
+}
+
+export function formattedValue(value, quotes = true) {
+ const type = valueType(value, false)
+ if (type !== 'custom' && value?._custom) {
+ value = value._custom.value
+ }
+ const result = specialTokenToString(value)
+ if (result) {
+ return result
+ }
+ else if (type === 'custom') {
+ return value._custom.display
+ }
+ else if (type === 'array') {
+ return `Array[${value.length}]`
+ }
+ else if (type === 'plain-object') {
+ return `Object${Object.keys(value).length ? '' : ' (empty)'}`
+ }
+ else if (type.includes('native')) {
+ return escape(specialTypeRE.exec(value)[2])
+ }
+ else if (typeof value === 'string') {
+ const typeMatch = value.match(rawTypeRE)
+ if (typeMatch) {
+ value = escape(typeMatch[1])
+ }
+ else if (quotes) {
+ value = `"${escape(value)}"`
+ }
+ else {
+ value = escape(value)
+ }
+ value = value.replace(/ /g, ' ')
+ .replace(/\n/g, '\\n')
+ }
+ return value
+}
+
+export function valueDetails(value: string) {
+ const matched = specialTypeRE.exec(value)
+ if (matched) {
+ const [,,,, param] = matched
+ return param
+ }
+ return null
+}
diff --git a/vue-devtools/packages/app-frontend/src/util/keyboard.ts b/vue-devtools/packages/app-frontend/src/util/keyboard.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cb7f28744ee0c2ade228f0981aa9b06d521fa342
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/util/keyboard.ts
@@ -0,0 +1,37 @@
+import { onMounted, onUnmounted } from 'vue'
+
+type KeyboardHandler = (event: KeyboardEvent) => boolean | void | Promise
+
+function handleKeyboard(type: 'keyup' | 'keydown', cb: KeyboardHandler, force: boolean) {
+ function handler(event: KeyboardEvent) {
+ if (!force && (
+ typeof HTMLElement !== 'undefined' && event.target instanceof HTMLElement && (
+ event.target.tagName === 'INPUT'
+ || event.target.tagName === 'TEXTAREA'
+ )
+ )) {
+ return
+ }
+
+ const result = cb(event)
+ if (result === false) {
+ event.preventDefault()
+ }
+ }
+
+ onMounted(() => {
+ document.addEventListener(type, handler)
+ })
+
+ onUnmounted(() => {
+ document.removeEventListener(type, handler)
+ })
+}
+
+export function onKeyUp(cb: KeyboardHandler, force = false) {
+ handleKeyboard('keyup', cb, force)
+}
+
+export function onKeyDown(cb: KeyboardHandler, force = false) {
+ handleKeyboard('keydown', cb, force)
+}
diff --git a/vue-devtools/packages/app-frontend/src/util/queue.ts b/vue-devtools/packages/app-frontend/src/util/queue.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3fd4238b25051ea72b5f0b76039122fa769b074e
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/util/queue.ts
@@ -0,0 +1,48 @@
+export class Queue {
+ private existsMap: Map = new Map()
+ private firstItem: QueueItem | null = null
+ private lastItem: QueueItem | null = null
+
+ add(value: T) {
+ if (!this.existsMap.has(value)) {
+ this.existsMap.set(value, true)
+ const item = {
+ current: value,
+ next: null,
+ }
+ if (!this.firstItem) {
+ this.firstItem = item
+ }
+ if (this.lastItem) {
+ this.lastItem.next = item
+ }
+ this.lastItem = item
+ }
+ }
+
+ shift(): T | null {
+ if (this.firstItem) {
+ const item = this.firstItem
+ this.firstItem = item.next
+ if (!this.firstItem) {
+ this.lastItem = null
+ }
+ this.existsMap.delete(item.current)
+ return item.current
+ }
+ return null
+ }
+
+ isEmpty() {
+ return !this.firstItem
+ }
+
+ has(value: T) {
+ return this.existsMap.has(value)
+ }
+}
+
+interface QueueItem {
+ current: T
+ next: QueueItem | null
+}
diff --git a/vue-devtools/packages/app-frontend/src/util/reactivity.ts b/vue-devtools/packages/app-frontend/src/util/reactivity.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e80d07a85c5115154bc2c2244225d383871914ba
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/util/reactivity.ts
@@ -0,0 +1,39 @@
+import type { Ref } from 'vue'
+import { watch } from 'vue'
+import { getStorage, setStorage } from '@vue-devtools/shared-utils'
+
+export function nonReactive(ref: Ref) {
+ const holder = {
+ value: ref.value,
+ }
+
+ watch(ref, (value) => {
+ holder.value = value
+ }, {
+ flush: 'sync',
+ })
+
+ return holder
+}
+
+export function addNonReactiveProperties(target: T, props: Partial) {
+ for (const key in props) {
+ Object.defineProperty(target, key, {
+ value: props[key],
+ writable: true,
+ enumerable: true,
+ configurable: false,
+ })
+ }
+}
+
+export function useSavedRef(ref: Ref, storageKey: string) {
+ const savedValue = getStorage(storageKey)
+ if (savedValue != null) {
+ ref.value = savedValue
+ }
+
+ watch(ref, (value) => {
+ setStorage(storageKey, value)
+ })
+}
diff --git a/vue-devtools/packages/app-frontend/src/util/shared-data.ts b/vue-devtools/packages/app-frontend/src/util/shared-data.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9b708f35f39466f6cae1f85c1e1b78f084049a48
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/util/shared-data.ts
@@ -0,0 +1,10 @@
+import { onUnmounted } from 'vue'
+import { watchSharedData } from '@vue-devtools/shared-utils'
+
+export function onSharedDataChange(prop, handler) {
+ const off = watchSharedData(prop, handler)
+
+ onUnmounted(() => {
+ off()
+ })
+}
diff --git a/vue-devtools/packages/app-frontend/src/util/theme.ts b/vue-devtools/packages/app-frontend/src/util/theme.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b40ba1b7c50031a0802114a0c20b5fc0c09a5c2a
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/util/theme.ts
@@ -0,0 +1,9 @@
+import { computed, ref } from 'vue'
+
+export const darkMode = ref(false)
+
+export function useDarkMode() {
+ return {
+ darkMode: computed(() => darkMode.value),
+ }
+}
diff --git a/vue-devtools/packages/app-frontend/src/util/time.ts b/vue-devtools/packages/app-frontend/src/util/time.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a0015f530d033737137e452507c73785bde6bc82
--- /dev/null
+++ b/vue-devtools/packages/app-frontend/src/util/time.ts
@@ -0,0 +1,17 @@
+import type { Ref } from 'vue'
+import { computed, ref } from 'vue'
+
+export const reactiveNow = ref(Date.now())
+
+setInterval(() => {
+ reactiveNow.value = Date.now()
+}, 100)
+
+export function useTimeAgo(time: Ref) {
+ return {
+ timeAgo: computed(() => {
+ const diff = reactiveNow.value - time.value
+ return `${Math.round(diff / 1000)}s ago`
+ }),
+ }
+}
diff --git a/vue-devtools/packages/build-tools/package.json b/vue-devtools/packages/build-tools/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..b239aeea406561b406dfd4d3c7c22c6f067ab6e2
--- /dev/null
+++ b/vue-devtools/packages/build-tools/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "@vue-devtools/build-tools",
+ "version": "0.0.0",
+ "private": true,
+ "main": "src/index.js",
+ "dependencies": {
+ "@babel/core": "^7.16.0",
+ "@babel/preset-env": "^7.16.4",
+ "@vue/compiler-sfc": "^3.3.4",
+ "babel-loader": "^8.2.3",
+ "css-loader": "^5.2.4",
+ "esbuild": "^0.11.20",
+ "esbuild-loader": "^2.13.0",
+ "friendly-errors-webpack-plugin": "^1.7.0",
+ "monaco-editor-webpack-plugin": "^3.1.0",
+ "path-browserify": "^1.0.1",
+ "postcss-loader": "^5.2.0",
+ "style-resources-loader": "^1.2.1",
+ "stylus": "^0.54.5",
+ "stylus-loader": "^5.0.0",
+ "terser-webpack-plugin": "^5.1.1",
+ "vue-loader": "^17.2.2",
+ "webpack": "^5.90.1",
+ "webpack-merge": "^5.10.0"
+ }
+}
diff --git a/vue-devtools/packages/build-tools/src/createConfig.js b/vue-devtools/packages/build-tools/src/createConfig.js
new file mode 100644
index 0000000000000000000000000000000000000000..92652e4a0b14475e3ef96e94ec77914e3dc29d6c
--- /dev/null
+++ b/vue-devtools/packages/build-tools/src/createConfig.js
@@ -0,0 +1,189 @@
+const webpack = require('webpack')
+const { mergeWithRules } = require('webpack-merge')
+const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
+const { VueLoaderPlugin } = require('vue-loader')
+const MonacoEditorPlugin = require('monaco-editor-webpack-plugin')
+
+exports.createConfig = (config, target = { chrome: 52, firefox: 48 }) => {
+ const mode = process.env.NODE_ENV === 'production' ? 'production' : 'development'
+ // const workspace = path.basename(process.cwd())
+
+ const baseConfig = {
+ mode,
+ resolve: {
+ extensions: ['.js', '.ts', '.vue'],
+ alias: {
+ '@front': '@vue-devtools/app-frontend/src',
+ '@back': '@vue-devtools/app-backend-core/lib',
+ 'vue': require.resolve('vue/dist/vue.esm-bundler.js'),
+ },
+ // symlinks: false,
+ fallback: {
+ path: require.resolve('path-browserify'),
+ },
+ },
+ module: {
+ rules: [
+ {
+ test: /\.js$/,
+ exclude: /node_modules|vue\/dist|vuex\/dist/,
+ loader: 'babel-loader',
+ },
+ {
+ test: /\.ts$/,
+ loader: 'esbuild-loader',
+ options: {
+ loader: 'ts',
+ target: 'es2015',
+ },
+ },
+ {
+ test: /\.vue$/,
+ loader: 'vue-loader',
+ options: {
+ compilerOptions: {
+ preserveWhitespace: false,
+ },
+ isServerBuild: false,
+ transpileOptions: {
+ target,
+ objectAssign: 'Object.assign',
+ transforms: {
+ modules: false,
+ },
+ },
+ },
+ },
+ {
+ test: /\.(css|postcss|pcss)$/,
+ use: [
+ 'vue-style-loader',
+ 'css-loader',
+ 'postcss-loader',
+ ],
+ },
+ {
+ test: /\.styl(us)?$/,
+ use: [
+ 'vue-style-loader',
+ 'css-loader',
+ 'postcss-loader',
+ 'stylus-loader',
+ {
+ loader: 'style-resources-loader',
+ options: {
+ patterns: [
+ require.resolve('@vue-devtools/app-frontend/src/assets/style/imports.styl'),
+ ],
+ },
+ },
+ ],
+ },
+ {
+ test: /\.svg$/,
+ loader: 'svg-inline-loader',
+ exclude: /assets/,
+ },
+ {
+ test: /\.(png|woff2|ttf|svg)$/,
+ type: 'asset/inline',
+ exclude: /@akryum\/md-icons-svg\/svg/,
+ },
+ ],
+ },
+ performance: {
+ hints: false,
+ },
+ plugins: [
+ new VueLoaderPlugin(),
+ ...(process.env.VUE_DEVTOOL_TEST ? [] : [new FriendlyErrorsPlugin()]),
+ new webpack.DefinePlugin({
+ 'process.env.RELEASE_CHANNEL': JSON.stringify(process.env.RELEASE_CHANNEL || 'stable'),
+ '__VUE_OPTIONS_API__': true,
+ '__VUE_PROD_DEVTOOLS__': true,
+ }),
+ new MonacoEditorPlugin({
+ // https://github.com/Microsoft/monaco-editor-webpack-plugin#options
+ languages: ['javascript'],
+ }),
+ ],
+ devtool: 'eval-source-map',
+ devServer: {
+ port: process.env.PORT,
+ },
+ stats: {
+ colors: true,
+ },
+ // cache: {
+ // type: 'filesystem',
+ // cacheDirectory: path.resolve(process.cwd(), 'node_modules/.cache/webpack'),
+ // name: `${workspace}-${mode}`
+ // },
+ snapshot: {
+ managedPaths: [],
+ },
+ }
+
+ if (process.env.NODE_ENV === 'production') {
+ const TerserPlugin = require('terser-webpack-plugin')
+ baseConfig.plugins.push(
+ new webpack.DefinePlugin({
+ 'process.env.NODE_ENV': '"production"',
+ }),
+ )
+ baseConfig.optimization = {
+ minimizer: [
+ new TerserPlugin({
+ exclude: /backend/,
+ terserOptions: {
+ compress: {
+ // turn off flags with small gains to speed up minification
+ arrows: false,
+ collapse_vars: false,
+ comparisons: false,
+ computed_props: false,
+ hoist_funs: false,
+ hoist_props: false,
+ hoist_vars: false,
+ inline: false,
+ loops: false,
+ negate_iife: false,
+ properties: false,
+ reduce_funcs: false,
+ reduce_vars: false,
+ switches: false,
+ toplevel: false,
+ typeofs: false,
+
+ // a few flags with noticable gains/speed ratio
+ // numbers based on out of the box vendor bundle
+ booleans: true,
+ if_return: true,
+ sequences: true,
+ unused: true,
+
+ // required features to drop conditional branches
+ conditionals: true,
+ dead_code: true,
+ evaluate: true,
+ },
+ mangle: {
+ safari10: true,
+ },
+ },
+ parallel: false,
+ }),
+ ],
+ }
+ }
+
+ return mergeWithRules({
+ module: {
+ rules: {
+ test: 'match',
+ loader: 'replace',
+ options: 'merge',
+ },
+ },
+ })(baseConfig, config)
+}
diff --git a/vue-devtools/packages/build-tools/src/index.js b/vue-devtools/packages/build-tools/src/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..58a59684cd2c8979b6ec20dc15c6a589bfffd84f
--- /dev/null
+++ b/vue-devtools/packages/build-tools/src/index.js
@@ -0,0 +1,3 @@
+Object.assign(module.exports, {
+ ...require('./createConfig'),
+})
diff --git a/vue-devtools/packages/docs/package.json b/vue-devtools/packages/docs/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..ea755e0df30cdede9e1ecdaa5ee02dc2d21af88e
--- /dev/null
+++ b/vue-devtools/packages/docs/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "@vue-devtools/docs",
+ "version": "0.0.0",
+ "devDependencies": {
+ "vitepress": "^0.22.3",
+ "vue": "^3.2.0"
+ }
+}
diff --git a/vue-devtools/packages/docs/postcss.config.js b/vue-devtools/packages/docs/postcss.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..1c6b09ca542b6369937127241873f41e0f93f8ec
--- /dev/null
+++ b/vue-devtools/packages/docs/postcss.config.js
@@ -0,0 +1,9 @@
+const path = require('node:path')
+
+module.exports = {
+ plugins: [
+ require('autoprefixer'),
+ require('tailwindcss')(path.resolve(__dirname, './tailwind.config.cjs')),
+ require('postcss-nested'),
+ ],
+}
diff --git a/vue-devtools/packages/docs/src/.vitepress/.gitignore b/vue-devtools/packages/docs/src/.vitepress/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..849ddff3b7ec917b5f4563e9a6d3ea63ea512a70
--- /dev/null
+++ b/vue-devtools/packages/docs/src/.vitepress/.gitignore
@@ -0,0 +1 @@
+dist/
diff --git a/vue-devtools/packages/docs/src/.vitepress/config.js b/vue-devtools/packages/docs/src/.vitepress/config.js
new file mode 100644
index 0000000000000000000000000000000000000000..e834b2677de8ff845d19e6788892fcd34d45d799
--- /dev/null
+++ b/vue-devtools/packages/docs/src/.vitepress/config.js
@@ -0,0 +1,71 @@
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ title: 'Vue Devtools',
+ description: 'Browser devtools extension for debugging Vue.js applications',
+
+ head: [
+ ['link', { rel: 'icon', type: 'image/svg+xml', href: '/favicon.svg' }],
+ ['link', { rel: 'icon', type: 'image/png', href: '/favicon.png' }],
+ ],
+
+ themeConfig: {
+ repo: 'vuejs/devtools',
+ logo: '/logo-header.svg',
+ docsDir: 'packages/docs/src',
+ docsBranch: 'main',
+ editLinks: true,
+ editLinkText: 'Suggest changes to this page',
+
+ algolia: {
+ appId: 'CFRGFZ1IGJ',
+ apiKey: 'cf7b3ddb7b310746c27c1a71ff7d4fe2',
+ indexName: 'devtools-vuejs',
+ },
+
+ nav: [
+ { text: 'Guide', link: '/guide/installation' },
+ {
+ text: 'Plugins',
+ items: [
+ { text: 'Plugin development guide', link: '/plugin/plugins-guide' },
+ { text: 'API Reference', link: '/plugin/api-reference' },
+ ],
+ },
+ {
+ text: '💚️ Sponsor',
+ link: 'https://github.com/sponsors/Akryum',
+ },
+ ],
+
+ sidebar: {
+ '/guide/': [
+ {
+ text: 'Guide',
+ children: [
+ {
+ text: 'Installation',
+ link: '/guide/installation',
+ },
+ {
+ text: 'Open in editor',
+ link: '/guide/open-in-editor',
+ },
+ {
+ text: 'F.A.Q.',
+ link: '/guide/faq',
+ },
+ {
+ text: 'Contributing',
+ link: '/guide/contributing',
+ },
+ {
+ text: 'Devtools performance',
+ link: '/guide/devtools-perf',
+ },
+ ],
+ },
+ ],
+ },
+ },
+})
diff --git a/vue-devtools/packages/docs/src/.vitepress/theme/custom.css b/vue-devtools/packages/docs/src/.vitepress/theme/custom.css
new file mode 100644
index 0000000000000000000000000000000000000000..cb84e107ad5e2a53742ff961fa559936d1027a4c
--- /dev/null
+++ b/vue-devtools/packages/docs/src/.vitepress/theme/custom.css
@@ -0,0 +1,15 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+.nav-bar-title .logo {
+ margin-top: 6px;
+}
+
+.home-hero {
+ figure {
+ .image {
+ max-height: 100px;
+ }
+ }
+}
diff --git a/vue-devtools/packages/docs/src/.vitepress/theme/index.js b/vue-devtools/packages/docs/src/.vitepress/theme/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..42fe9a936179c5c200dcb89b4c99225794e4c920
--- /dev/null
+++ b/vue-devtools/packages/docs/src/.vitepress/theme/index.js
@@ -0,0 +1,4 @@
+import DefaultTheme from 'vitepress/theme'
+import './custom.css'
+
+export default DefaultTheme
diff --git a/vue-devtools/packages/docs/src/assets/chrome-settings1.png b/vue-devtools/packages/docs/src/assets/chrome-settings1.png
new file mode 100644
index 0000000000000000000000000000000000000000..9aa644cb1d921db4035e03afefdde7a4fd776313
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/chrome-settings1.png differ
diff --git a/vue-devtools/packages/docs/src/assets/chrome-settings2.png b/vue-devtools/packages/docs/src/assets/chrome-settings2.png
new file mode 100644
index 0000000000000000000000000000000000000000..43fbea14fa71a7ec0e4894e319c779198b4d58db
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/chrome-settings2.png differ
diff --git a/vue-devtools/packages/docs/src/assets/dev-shell-profile-export.png b/vue-devtools/packages/docs/src/assets/dev-shell-profile-export.png
new file mode 100644
index 0000000000000000000000000000000000000000..57567d5a58328eb0a00b3f113b18a28166c321f5
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/dev-shell-profile-export.png differ
diff --git a/vue-devtools/packages/docs/src/assets/dev-shell-profile-start.png b/vue-devtools/packages/docs/src/assets/dev-shell-profile-start.png
new file mode 100644
index 0000000000000000000000000000000000000000..5cef3a9de523210ad455d8cb70725a069f6c575f
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/dev-shell-profile-start.png differ
diff --git a/vue-devtools/packages/docs/src/assets/dev-shell-profile-stop.png b/vue-devtools/packages/docs/src/assets/dev-shell-profile-stop.png
new file mode 100644
index 0000000000000000000000000000000000000000..dd07f1ebe571f142bb5d375d05e91423e6db2355
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/dev-shell-profile-stop.png differ
diff --git a/vue-devtools/packages/docs/src/assets/dev-shell-url.png b/vue-devtools/packages/docs/src/assets/dev-shell-url.png
new file mode 100644
index 0000000000000000000000000000000000000000..8df2b0b11e54425431dd7c38bac83aa4b180f0df
--- /dev/null
+++ b/vue-devtools/packages/docs/src/assets/dev-shell-url.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:788541a1596d5a1637fe4a37cd63773536f942d6ae55d3e8169f38f6862bad9b
+size 105737
diff --git a/vue-devtools/packages/docs/src/assets/devtools-version.png b/vue-devtools/packages/docs/src/assets/devtools-version.png
new file mode 100644
index 0000000000000000000000000000000000000000..bda35c25812c5ab123520f7c075cda95eaf089ab
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/devtools-version.png differ
diff --git a/vue-devtools/packages/docs/src/assets/edge-settings1.png b/vue-devtools/packages/docs/src/assets/edge-settings1.png
new file mode 100644
index 0000000000000000000000000000000000000000..bbe6180535ffc796a7b8a2fc4e877cf877b7e5cc
--- /dev/null
+++ b/vue-devtools/packages/docs/src/assets/edge-settings1.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d01a761a3a9ac46b0afe63e5eb2ff0aeabe3ef4eb8be41204100d1963ee6c5b1
+size 124760
diff --git a/vue-devtools/packages/docs/src/assets/edge-settings2.png b/vue-devtools/packages/docs/src/assets/edge-settings2.png
new file mode 100644
index 0000000000000000000000000000000000000000..d064b9b9c9d1beeb9b4bc8998c19f1547caa7a5d
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/edge-settings2.png differ
diff --git a/vue-devtools/packages/docs/src/assets/firefox-settings1.png b/vue-devtools/packages/docs/src/assets/firefox-settings1.png
new file mode 100644
index 0000000000000000000000000000000000000000..9247d297ccacebefe2ba6b62cd0e82f1a12cd687
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/firefox-settings1.png differ
diff --git a/vue-devtools/packages/docs/src/assets/firefox-settings2.png b/vue-devtools/packages/docs/src/assets/firefox-settings2.png
new file mode 100644
index 0000000000000000000000000000000000000000..73c27f82e1e1cc5b31c117ab744b307aee1880a9
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/firefox-settings2.png differ
diff --git a/vue-devtools/packages/docs/src/assets/firefox-settings3.png b/vue-devtools/packages/docs/src/assets/firefox-settings3.png
new file mode 100644
index 0000000000000000000000000000000000000000..884f8d0c572308030c57f2a133e624c3d991aa0b
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/firefox-settings3.png differ
diff --git a/vue-devtools/packages/docs/src/assets/open-in-editor.png b/vue-devtools/packages/docs/src/assets/open-in-editor.png
new file mode 100644
index 0000000000000000000000000000000000000000..299a386e5c41ce514187def8c08122a841ab72cd
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/open-in-editor.png differ
diff --git a/vue-devtools/packages/docs/src/assets/plugin-components-tags.png b/vue-devtools/packages/docs/src/assets/plugin-components-tags.png
new file mode 100644
index 0000000000000000000000000000000000000000..ef88ec1a746018c96d8f175989f366b5289882ea
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/plugin-components-tags.png differ
diff --git a/vue-devtools/packages/docs/src/assets/plugin-custom-inspector-menu.png b/vue-devtools/packages/docs/src/assets/plugin-custom-inspector-menu.png
new file mode 100644
index 0000000000000000000000000000000000000000..3ea6eaaa3489ee26e54c392e7d3f82ecd8625a5b
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/plugin-custom-inspector-menu.png differ
diff --git a/vue-devtools/packages/docs/src/assets/plugin-custom-inspector-state.png b/vue-devtools/packages/docs/src/assets/plugin-custom-inspector-state.png
new file mode 100644
index 0000000000000000000000000000000000000000..b384724c7915f3666feb7899a1d91a09b9e328dc
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/plugin-custom-inspector-state.png differ
diff --git a/vue-devtools/packages/docs/src/assets/plugin-custom-inspector-tree.png b/vue-devtools/packages/docs/src/assets/plugin-custom-inspector-tree.png
new file mode 100644
index 0000000000000000000000000000000000000000..7b52661bf779222d80225a4adf59dfe1688b45be
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/plugin-custom-inspector-tree.png differ
diff --git a/vue-devtools/packages/docs/src/assets/plugin-settings.png b/vue-devtools/packages/docs/src/assets/plugin-settings.png
new file mode 100644
index 0000000000000000000000000000000000000000..13fd41287879bc58b353cd83281d7962424e2d54
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/plugin-settings.png differ
diff --git a/vue-devtools/packages/docs/src/assets/plugin-timeline-example1.png b/vue-devtools/packages/docs/src/assets/plugin-timeline-example1.png
new file mode 100644
index 0000000000000000000000000000000000000000..ae8d7aef93d34264d1337bbf9d2ec2a77a54fdeb
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/plugin-timeline-example1.png differ
diff --git a/vue-devtools/packages/docs/src/assets/plugin-timeline-example2.png b/vue-devtools/packages/docs/src/assets/plugin-timeline-example2.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a607524e7d1737e5afee77d8568ba9ead90f0db
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/plugin-timeline-example2.png differ
diff --git a/vue-devtools/packages/docs/src/assets/plugin-timeline-group-state.png b/vue-devtools/packages/docs/src/assets/plugin-timeline-group-state.png
new file mode 100644
index 0000000000000000000000000000000000000000..2c35c879b69f68153afa69cf3442cd62a0d966e3
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/plugin-timeline-group-state.png differ
diff --git a/vue-devtools/packages/docs/src/assets/plugin-timeline-group.png b/vue-devtools/packages/docs/src/assets/plugin-timeline-group.png
new file mode 100644
index 0000000000000000000000000000000000000000..75650332026b913219f6d8f30852fcd15dcd473d
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/plugin-timeline-group.png differ
diff --git a/vue-devtools/packages/docs/src/assets/plugin-timeline-layer.png b/vue-devtools/packages/docs/src/assets/plugin-timeline-layer.png
new file mode 100644
index 0000000000000000000000000000000000000000..b942bb7d7b011f98ae1eb5778d13260275cb9dd4
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/plugin-timeline-layer.png differ
diff --git a/vue-devtools/packages/docs/src/assets/pluygin-components-state.png b/vue-devtools/packages/docs/src/assets/pluygin-components-state.png
new file mode 100644
index 0000000000000000000000000000000000000000..b6a9c81997d8856f6e38537e86095d0892b7cb0d
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/pluygin-components-state.png differ
diff --git a/vue-devtools/packages/docs/src/assets/vue-devtools-architecture.drawio b/vue-devtools/packages/docs/src/assets/vue-devtools-architecture.drawio
new file mode 100644
index 0000000000000000000000000000000000000000..72b15ad7207089d07b8b05bc9ec01aed34ab4473
--- /dev/null
+++ b/vue-devtools/packages/docs/src/assets/vue-devtools-architecture.drawio
@@ -0,0 +1 @@
+7V1Zb9s4EP41fmwgibr8GDt2W2ALBG33aN8YiZa5lUVBohN7f/2Stm7SsZxKot0qKFCROjnfzDfD4eEJmG927xMYrz8RH4UTQ/N3E/AwMQwd6Br7j9fsjzUOcI4VQYL97KKy4gv+D2WV2X3BFvsorV1ICQkpjuuVHoki5NFaHUwS8lK/bEXC+ltjGCCh4osHQ7H2b+zT9bHWNZyy/gPCwTp/s25Pj2c2ML84a0m6hj55qVWhHV2SiGaf+Jk8ETqxFmtKeePuJ8aS/VvxC+4CQoIQwRindx7ZsGovZZcsV3CDQy7Z473soWAxAfOEsMLhaLObo5Ajkgv7+OblibNFaxMU0TY3fDZWBtY/36f0E1i8Xzx//77X3gHz+JhnGG4zMWYioPtcrgnZRj7iT9EnYPayxhR9iaHHz74wTWJ1a7oJs9MpTciPQv6skTMulWXe+L9Q4sMIZtVzEpLk8BJgaXPXcXk9DsO8PiIRe8vMh+m6eD8vPEJKURIdagytfG3leYu5PjNMdiZrH0oo2p2UnF7gwawDkQ2iyZ5dkt1gaJkS5IbhZOWXUs1ArijrqopNs0qY6U1QPLsEih1kWF2Am6Orwk2QtKbN7t1FR5I2GpKeipI2XJmkrb4kDYzRQi62ELuthTi9waaNsF0MW1E+B5tp9oWb+2vymlkXNJDxminjtd4M5HocyHJmA2faj6CL8llBa30JuggqS8EinwWuWZEkdE0CEsFwUdbOStFrrFRe8wchcSbwfxGl+ywKh1tK6nCgHab/8NvvrKz0rXLmYZc9+VDY54WItfd4k2Hl5W/Vk+V9h1J+44VMWKM9QR2AaU6t0u64rF5XBiZask089BoGx+soTAJEXwur5MqVoBBS/Fz/ju4VRbDIv9hBh0YJBHFnfqgB1PLw9wquFU/Wtf06Dft1RfuVxX+9+aNCxa7eemtWdaFFnjbCCic4F3FCyoyN3vNuPavwQpim2MurlzjMW9qhkYNbMHIgGPljuA1wdAN2PrUd3wPd2DlwjPN2bg5o55aAy58pSljNfRwL2LB2UxkATXGLET8MccDDe4/JiT0ezLgUsQfD++zEBvv+gUNkiNd55RUbz+lJl4A+cLQ1lbC10RtbA7Vs7VTpumDoc8FWnVj1M8TaMnq60AN0yMP2LfCwYanVFGOAsPyX0RT9BA0Noyq24BpmCebNv36XrWlP0EUduexGbtaSJIuGDc3FjMVowkObsNPShG2VFuwIFvyBkB83Yb/d5SCb9msCxfYL3DFYu8h+ZwtNM0C39psP3p/3wYZSC7aV6kpVUUre75jraxmTjD6q6RLtrSqUtU/XRJVaLmdzdtBQVCX6pdZDKOYiBbFEq/Rcb/qGIr+h6qymougqVNABKlXQVTpOpE/eRnGXJYVHFTyngkq9bP6ZY1e3Hiq7uuqurtrw5/ZC5T66uno+qfWq+7pgTGxeQa+qraqo7VXln1kdjUzIbn8DdL9aPXnA74fuLddSS/dgpPsrsGGjrQ0rHZ3IF2mMfH8TuqIp5XtDjO+h9yM4qMMNkH6fMb6tmvR1cWoQBwdJkLnl+SdDT6sedP6Jo5iM3+S4a0xc8eIX53CGzll3SeCtpyKoJXBxLsKcbGImd9Zgww45Kzwl7CjgRx+jNEYeZXL7vajdAI30jepJxEDsZ834elc+wbAJ2lf41APfh2hFVbB9l6uV9BarlQZleyD32Hk41UT2EUoSqSO0MmhtRwzGBoXWFDPhaIPplUZiLdYRnsC4C7ZtLNkAlmiWshVX/WEnsu3948cROkkfyD0Pna4Pip1Iqen19oDUgtfgTNMBiu1O3EsixClF4tqWET1memYDPVMxeuIKmNHyTni8aaN/odzjid3CDUrTQ7zJ2pWmOApGIGXbjTh3Vj3wnIqB56BQWmLgKSCXrmHMD32yfQpRln2Z+ThhnX1MuOhSsuVff1nPvv26Ue3wJ/ZBuoDEbkJiSRaV5YPcNUh62yrBGh3bBQBaDXI0FJOjJTq2B/TMdyZLxz76T/TRZbtgDdpHt6YCUtc6YfJnxywLwj22uJvl8qYc7taZ7OzWR4J58jlXE7PZLWnuzHVMsWd3lSrA3BjcVy6L+QXp6fdYjbEfV3erjzt7ff5dpQYev6DUx0Imb1dRW5JGYsej3xDpxdQb+EiWJw3qN2zjfCTGHoPj9JR0K3DCw0gMK6zwjov4zduJnQq9zupLx2MsVsPNG6YYOAMJXKA3uMTM0fMWvfMLV3+VJqd+DN1ujqpIOrODunVbjNdu3O6mtvMw72jjFMHuJFMehrU7MffwjYUerKaMsrUTe9zcbmDdJaSCBUpyEMX+psOYoLhg+sZNsDFnpFMTBEC16xM3zZwz0R3mhGipl+C4j4FLVabXJZRN0wOSXNOwpucq3m/OeMMMsmKq90/PIPu1VwHme55d+SSz/DOrdLJNKd/LfpxhNpF2VpXPMHOU5sKUrBj5fWij7caWimlD7IB/xRsU4ui3Xz6smh1ckdHHAayT6DVmZigf3XfHOVGt/XJz5rfqwUdXTGYtk0Pf7FrxU5+RbI4gyX4EpqOM5ISjkf8A03HQp/xtLLD4Hw==
\ No newline at end of file
diff --git a/vue-devtools/packages/docs/src/assets/vue-devtools-architecture.png b/vue-devtools/packages/docs/src/assets/vue-devtools-architecture.png
new file mode 100644
index 0000000000000000000000000000000000000000..f7860dec25038252bf8f6f146308fe56e1949451
Binary files /dev/null and b/vue-devtools/packages/docs/src/assets/vue-devtools-architecture.png differ
diff --git a/vue-devtools/packages/docs/src/assets/vue-devtools-architecture.svg b/vue-devtools/packages/docs/src/assets/vue-devtools-architecture.svg
new file mode 100644
index 0000000000000000000000000000000000000000..443c53e987d625e0516d802bfc61c3458da6780f
--- /dev/null
+++ b/vue-devtools/packages/docs/src/assets/vue-devtools-architecture.svg
@@ -0,0 +1,1676 @@
+
+
diff --git a/vue-devtools/packages/docs/src/components/InstallButton.vue b/vue-devtools/packages/docs/src/components/InstallButton.vue
new file mode 100644
index 0000000000000000000000000000000000000000..927635c381a900164eddb0adcaff4feaa6de181d
--- /dev/null
+++ b/vue-devtools/packages/docs/src/components/InstallButton.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+ {{ label }}
+
+
diff --git a/vue-devtools/packages/docs/src/components/InstallButtons.vue b/vue-devtools/packages/docs/src/components/InstallButtons.vue
new file mode 100644
index 0000000000000000000000000000000000000000..78627d4532ebcad234985ed2b9df76b1d24caca9
--- /dev/null
+++ b/vue-devtools/packages/docs/src/components/InstallButtons.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/docs/src/devtools-vue3.md b/vue-devtools/packages/docs/src/devtools-vue3.md
new file mode 100644
index 0000000000000000000000000000000000000000..09ae2e2c3eea4c30f1e8ba7a08a2ea5d8c596b1a
--- /dev/null
+++ b/vue-devtools/packages/docs/src/devtools-vue3.md
@@ -0,0 +1,25 @@
+# How to Setup Vue DevTools for Vue 3
+
+## Local Development
+
+```bash
+# Clone repo
+git clone git@github.com:vuejs/vue-devtools.git
+
+# Change into devtools directory
+cd vue-devtools
+
+# Checkout next branch
+git checkout next
+
+# Install dependencies
+yarn
+
+# Build TypeScript dependencies
+yarn build:watch
+
+# Start local environment
+yarn dev:shell-vue3
+```
+
+Once everything is setup, you should be able to visit `http://localhost:8090/`
diff --git a/vue-devtools/packages/docs/src/guide/contributing.md b/vue-devtools/packages/docs/src/guide/contributing.md
new file mode 100644
index 0000000000000000000000000000000000000000..bcbb83bb62f279e63667dd58e35a7c060b48fb19
--- /dev/null
+++ b/vue-devtools/packages/docs/src/guide/contributing.md
@@ -0,0 +1,98 @@
+# Contributing
+
+Hi! We are really excited that you are interested in contributing to the Vue devtools. Before submitting your contribution, please make sure to take a moment and read through the following guide.
+
+## Monorepo
+
+The repository is a monorepo with several nested packages:
+
+|Package|Description|
+|-------|-----------|
+[api](https://github.com/vuejs/devtools/tree/main/packages/api) | The public devtools API that can be installed in Vue plugins |
+[app-backend-api](https://github.com/vuejs/devtools/tree/main/packages/app-backend-api) | Abstract API to link the Public API, the core and Vue handlers |
+[app-backend-core](https://github.com/vuejs/devtools/tree/main/packages/app-backend-core) | The main logic injected in the page to interact with Vue apps |
+[app-backend-vue1](https://github.com/vuejs/devtools/tree/main/packages/app-backend-vue1) | Decoupled handlers to support Vue 1 (soon) |
+[app-backend-vue2](https://github.com/vuejs/devtools/tree/main/packages/app-backend-vue2) | Decoupled handlers to support Vue 2 |
+[app-backend-vue3](https://github.com/vuejs/devtools/tree/main/packages/app-backend-vue3) | Decoupled handlers to support Vue 3 |
+[app-frontend](https://github.com/vuejs/devtools/tree/main/packages/app-frontend) | Vue app displayed in the browser devtools pane |
+[shell-chrome](https://github.com/vuejs/devtools/tree/main/packages/shell-chrome) | Chrome/Firefox extension |
+[shell-electron](https://github.com/vuejs/devtools/tree/main/packages/shell-electron) | Electron standalone app |
+[shell-host](https://github.com/vuejs/devtools/tree/main/packages/shell-host) | Development environment |
+[shell-dev-vue2](https://github.com/vuejs/devtools/tree/main/packages/shell-dev-vue2) | Demo app for development (Vue 2) |
+[shell-dev-vue3](https://github.com/vuejs/devtools/tree/main/packages/shell-dev-vue3) | Demo app for development (Vue 3) |
+
+## Development
+
+1. Clone [this repo](https://github.com/vuejs/devtools)
+2. Run `yarn install` in the repository root to install dependencies.
+3. Run `yarn run build:watch` (compiles and watch the packages) and then `yarn run dev:vue3` (run the development shell) in two different terminals. Wait for the initial compilation in the first terminal to finish before running the second command.
+4. A plain shell with a test app will be available at `http://localhost:8090`.
+
+## Pull Request Guidelines
+
+Thank you for your code contribution! Before opening a PR, please make sure to read the following:
+
+- Checkout a topic branch from a base branch, e.g. `main`, and merge back against that branch. For example: `feat/my-new-feature`.
+
+- Please make sure that you allow maintainers to push changes to your branch when you create your PR.
+
+- If adding a new feature:
+
+
+ - Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first and have it approved before working on it.
+
+- If fixing bug:
+
+ - If you are resolving a special issue, add `(fix #xxxx[,#xxxx])` (#xxxx is the issue id) in your PR title for a better release log, e.g. `fix: update entities encoding/decoding (fix #3899)`.
+ - Provide a detailed description of the bug in the PR. Live demo preferred.
+
+
+- It's OK to have multiple small commits as you work on the PR - GitHub can automatically squash them before merging.
+
+
+
+- Commit messages must follow the [commit message convention](https://github.com/vuejs/devtools/blob/main/.github/commit-convention.md) so that changelogs can be automatically generated.
+
+## Running tests
+
+1. Run `yarn lint` to check code quality with ESLint.
+2. Run `yarn test` to run all tests. (@TODO)
+
+## Testing as Chrome addon
+
+This is useful when you want to build the extension with the source repo to get not-yet-released features.
+
+1. Clone this repo
+2. `cd devtools` the newly created folder
+3. run `yarn install`
+4. then run `yarn run build:watch` & `yarn run dev:chrome` in parallel
+5. Open the Chrome extension page (currently under `Menu` > `More Tools` > `Extensions`)
+6. Check "developer mode" on the top-right corner
+7. Click the "load unpacked" button on the left, and choose the folder: `devtools/packages/shell-chrome/` (it will have an orange disk icon)
+8. Make sure you disable all other versions of the extension
+
+## Testing as Firefox addon
+
+1. Install `web-ext`
+
+ ~~~~
+ $ yarn global add web-ext
+ ~~~~
+
+ Also, make sure `PATH` is set up. Something like this in `~/.bash_profile`:
+
+ ~~~~
+ $ PATH=$PATH:$(yarn global bin)
+ ~~~~
+
+2. Clone this repo
+3. run `yarn install`
+4. then run `yarn run build:watch` and `yarn run dev:firefox` in parallel
+5. run `yarn run:firefox`
+
+## Docs development
+
+1. Clone this repo
+2. `cd devtools` the newly created folder
+3. run `yarn install`
+4. run `docs:dev`
diff --git a/vue-devtools/packages/docs/src/guide/custom-vue2-app-scan-selector.md b/vue-devtools/packages/docs/src/guide/custom-vue2-app-scan-selector.md
new file mode 100644
index 0000000000000000000000000000000000000000..ebad25f6c420c165810c2c01b1c66222562351fc
--- /dev/null
+++ b/vue-devtools/packages/docs/src/guide/custom-vue2-app-scan-selector.md
@@ -0,0 +1,12 @@
+## Customize vue2 app scan selector
+> For example, if you are using micro-app as your micro-frontend framework, the devtools cannot find Vue2 apps in `` by default.
+
+You can set a custom selector used to scan for Vue2 apps in your project with the following code in your frontend app:
+
+```js
+if (process.env.NODE_ENV !== 'production') {
+ window.VUE_DEVTOOLS_CONFIG = {
+ customVue2ScanSelector: 'micro-app'
+ }
+}
+```
diff --git a/vue-devtools/packages/docs/src/guide/devtools-perf.md b/vue-devtools/packages/docs/src/guide/devtools-perf.md
new file mode 100644
index 0000000000000000000000000000000000000000..c3706bad1493a06e7efcedab8d42fc4d25433749
--- /dev/null
+++ b/vue-devtools/packages/docs/src/guide/devtools-perf.md
@@ -0,0 +1,83 @@
+# Profiling devtools performance
+
+If you experience performance issues while using the devtools, this guide will explain how to profile the devtools and share the result to the team.
+
+## 1. Setup environment
+
+First you need to clone and setup the devtools repository as [explained in the contributing guide](./contributing.md#development).
+
+## 2. Run Chrome with web security disabled
+
+The development shell for the devtools is a page with a development version of the devtools and an iframe mimicking the page being inspected.
+
+Normally inspecting the iframe would only work on the same domain (here `localhost`), but we can workaround this limitation by disabling web security in Chrome.
+
+```bash
+/path/to/chrome --disable-web-security --disable-site-isolation-trials --user-data-dir="temp-chrome-data"
+```
+
+::: danger
+Do not browse to any other website while using this Chrome instance, as it will disable some security features.
+:::
+
+## 3. Open dev shell
+
+Make sure you have run both the `build:watch` and the `dev:vue3` scripts as [explained in the contributing guide](./contributing.md#development).
+
+In the Chrome window, open the devtools development shell at `http://localhost:8090`.
+
+You can then change the target URL in the toolbar on top of the devtools:
+
+
+
+## 4. Create a profiling session
+
+Open the Chrome devtools and go to the Performance tab.
+
+Start a performance recording by clicking the record button:
+
+
+
+Then try to reproduce the performance issues by using your application and the devtools for 10 or 20 seconds.
+
+## 5. Export the profiling data
+
+When your are done, stop the recording by clicking the stop button:
+
+
+
+Then click the "Save profile..." button to export the profiling data:
+
+
+
+## 6. Share the profiling data
+
+Check your Vue devtools version number in the Extensions tab of Chrome:
+
+
+
+Post a new comment [here](https://github.com/vuejs/devtools/discussions/1968) with the following information:
+
+- Run `npx envinfo --system --browsers` and paste the result. Make sure is contains your OS version and Chrome version.
+- Vue Devtools version.
+- Upadload the profiling data file in the comment (you can drag and drop it in the comment box).
+
+Example:
+
+```
+ System:
+ OS: Linux 5.19 Fedora Linux 36 (Workstation Edition)
+ CPU: (24) x64 AMD Ryzen 9 3900XT 12-Core Processor
+ Memory: 34.66 GB / 62.71 GB
+ Container: Yes
+ Shell: 5.1.16 - /bin/bash
+ Browsers:
+ Chrome: 106.0.5249.103
+ Firefox: 105.0.1
+
+ Vue Devtools version: 6.4.3
+
+ (Don't forget to upload the profile data file!)
+```
+
+Thank you for your contribution!
diff --git a/vue-devtools/packages/docs/src/guide/faq.md b/vue-devtools/packages/docs/src/guide/faq.md
new file mode 100644
index 0000000000000000000000000000000000000000..e4f26b624d18aebfaaccca686c061938d41933e4
--- /dev/null
+++ b/vue-devtools/packages/docs/src/guide/faq.md
@@ -0,0 +1,49 @@
+# Frequently Asked Questions
+
+## How to use the devtools in IE/Safari or any other browser?
+
+In case your browser doesn't have our browser extension available, we made a standalone Vue devtools application.
+[Get it now!](./installation.md#standalone)
+
+## When opening an HTML file directly
+
+Fixing "Download the Vue Devtools for a better development experience" console message when working locally over `file://` protocol:
+- Google Chrome: Right click on vue-devtools icon and click "Manage Extensions" then search for vue-devtools on the extensions list. Check the "Allow access to file URLs" box.
+
+## The Vue devtools don't show up
+
+Here are some troubleshooting steps to help you if you don't the Vue devtools in your browser:
+
+- Check if you have the extension [installed](./installation.md).
+- If you are on a live website, there is a good chance it's using a production build of Vue.
+ - Use a non-minified, non-`prod` version of Vue on CDN
+ - Set the `__VUE_PROD_DEVTOOLS__` environment variable for Vue 3 when using a bundler like Webpack ([more info](https://github.com/vuejs/core/tree/main/packages/vue#bundler-build-feature-flags)).
+- Try closing the devtools pane, refreshing the page and opening the devtools pane again.
+- Try restarting the browser or the computer.
+- If you have multiple versions of the Vue devtools installed, it's recommended to disable/remove the others.
+- Try disabling other devtools extensions like React devtools.
+- Look for errors in the browser Console.
+- Update your project dependencies.
+- Even if the Vue logo in the toolbar is gray and says "Vue not detected", open your browser devtools and check if the Vue tab is showing up anyway.
+
+## The data isn't updating in the component inspector
+
+Make sure your data is used somewhere in your templates. Vue uses a lazy reactivity system for performance reasons, so the devtools could read some component data but Vue might not trigger updates on it as you would expect.
+
+You can also click on the `Force refresh` button at the top of the devtools to do a manual refresh of the component data.
+
+## A weird gray overlay is displayed on my page when I move the mouse in the timeline
+
+By default, the devtools will try to take screenshots of your application when something happens on the Timeline. But it can fail for various reasons (such as undocking the devtools pane on Chrome). In that case, you can turn the screenshots off by opening the 'More' menu on the top right of the devtools (three vertical dots).
+
+## Some package is polluting my devtools
+
+The new Vue devtools feature a powerful public API so that package authors can integrate with the devtools (for example vuex or pinia). Since great power comes with great responsibility, you can disable specific permissions of a plugin, or even turn it off entirely, by going to the 'More' menu (three vertical dots on the top right), and then 'Devtools plugins...'.
+
+## I can't open a component in my editor
+
+This feature needs some setup in your project to work correctly. See [here](./open-in-editor.md) for more information.
+
+## Something is broken in the new devtools
+
+See [installing the previous version](./installation.md#legacy) for more information.
diff --git a/vue-devtools/packages/docs/src/guide/installation.md b/vue-devtools/packages/docs/src/guide/installation.md
new file mode 100644
index 0000000000000000000000000000000000000000..0546165d89b7f15cddb65f7da3f5c7d366c624d4
--- /dev/null
+++ b/vue-devtools/packages/docs/src/guide/installation.md
@@ -0,0 +1,209 @@
+
+
+# Installation
+
+::: tip Previous version
+If you want to install the previous version of the devtools (v5), see [here](#legacy).
+:::
+
+
+
+## Chrome
+
+Install the extension on the Chrome Web Store:
+
+
+
+### Beta
+
+To install the beta version of the devtools, remove or disable any existing versions and install the extension from [here](https://chrome.google.com/webstore/detail/vuejs-devtools/ljjemllljcmogpfapbkkighbhhppjdbg).
+
+
+
+### Settings
+
+If you need to use the devtools in incognito mode or when you open an HTML file directly, you need to change the extension settings.
+
+1. Go to the extensions:
+
+
+
+2. Click on the `Details` button on the Vue.js Devtools extension.
+
+3. Make sure the relevant settings are set:
+
+
+
+## Firefox
+
+Install the extension on the Mozilla Addons website:
+
+
+
+### Beta
+
+To install or update the beta version of the devtools, remove or disable any existing versions, go to one of repository beta releases and download the `xpi` file.
+
+
+
+### Settings
+
+If you need to use the devtools in incognito mode, you need to change the extension settings.
+
+1. Open **Menu** and click **Add-ons and Themes**
+
+
+
+2. Click on **Manage** Option on **Vue.js devtools** Extension Options
+
+
+
+3. Make sure the relevant settings are set:
+
+
+
+## Edge
+
+Install the extension on the Edge Store:
+
+
+
+### Settings
+
+If you need to use the devtools in InPrivate mode or when you open an HTML file directly, you need to change the extension settings.
+
+1. Go to the extension page:
+
+
+
+2. Make sure the relevant settings are set:
+
+
+
+## Standalone
+
+In case you are using an unsupported browser, or if you have other specific needs (for example your application is in Electron), you can use the standalone application.
+
+Install the package globally:
+```bash
+npm install -g @vue/devtools
+```
+
+Or locally as project dependency:
+```bash
+npm install --save-dev @vue/devtools
+```
+
+### Using global package
+
+Once you installed the package globally, run:
+```bash
+vue-devtools
+```
+
+Then add this code to the `` section of your application HTML file:
+```html
+
+```
+
+Or if you want to debug your device remotely:
+```html
+
+
+```
+
+**(Don't forget to remove it before deploying to production!)**
+
+`` usually looks like this: `192.168.x.x`.
+
+Then start your development server like you are used to, *without* killing the `vue-devtools` command (for example, open a new terminal). Both need to run in parallel.
+
+```bash
+yarn dev
+#or
+yarn serve
+```
+
+### Using dependency package
+
+Once you installed the package as project dependency, run:
+```bash
+./node_modules/.bin/vue-devtools
+```
+
+You can also use the global `vue-devtools` to start the app, but you might want to check if the local version matches the global one in this scenario to avoid any incompatibilities.
+
+Then import it directly in your app:
+```js
+import devtools from '@vue/devtools'
+// import Vue from 'vue'
+```
+> Make sure you import devtools before Vue, otherwise it might not work as expected.
+
+And connect to host:
+```js
+if (process.env.NODE_ENV === 'development') {
+ devtools.connect(/* host, port */)
+}
+```
+
+**host** - is an optional argument that tells your application where devtools middleware server is running, if you debug your app on your computer you don't have to set this (the default is `http://localhost`), but if you want to debug your app on mobile devices, you might want to pass your local IP (e.g. `http://192.168.1.12`).
+
+**port** - is an optional argument that tells your application on what port devtools middleware server is running. If you use proxy server, you might want to set it to `null` so the port won't be added to connection URL.
+
+[More details](https://github.com/vuejs/devtools/tree/main/packages/shell-electron#vue-remote-devtools)
+
+## Legacy
+
+If something is broken with the new devtools, please [submit a new issue](https://github.com/vuejs/devtools/issues/new/choose)!
+
+Meanwhile, you can install the legacy version (v5) of the devtools:
+
+
+
+
+
+
+
+Make sure you disable any other versions of the Vue devtools. Only one version should be enabled at a time.
diff --git a/vue-devtools/packages/docs/src/guide/open-in-editor.md b/vue-devtools/packages/docs/src/guide/open-in-editor.md
new file mode 100644
index 0000000000000000000000000000000000000000..288d00b742e5fb70e90d515083efd18c23e8cfaf
--- /dev/null
+++ b/vue-devtools/packages/docs/src/guide/open-in-editor.md
@@ -0,0 +1,63 @@
+# Open component in editor
+
+When you select a component, you have the option to open the corresponding source file in your code editor.
+
+
+
+To able to work, this feature may need some configuration in your project.
+
+## Vue CLI 3
+
+Vue CLI 3 supports this feature out-of-the-box when running `vue-cli-service serve`.
+
+## Nuxt & Quasar CLI
+
+Nuxt & Quasar CLI supports this feature out-of-the-box. Make sure to be in debug mode.
+
+## Webpack
+
+In your Vue project, install the [launch-editor-middleware](https://github.com/yyx990803/launch-editor#middleware) package and modify your webpack configuration:
+
+1. Import the package:
+
+```js
+const openInEditor = require('launch-editor-middleware')
+```
+
+2. In the `devServer` option, register the `/__open-in-editor` HTTP route:
+
+```js
+export default {
+ devServer: {
+ before(app) {
+ app.use('/__open-in-editor', openInEditor())
+ }
+ }
+}
+```
+
+3. The editor to launch is guessed. You can also specify the editor app with the `editor` option. See the [supported editors list](https://github.com/yyx990803/launch-editor#supported-editors).
+
+```js
+openInEditor('code')
+```
+
+4. You can now click on the name of the component in the Component inspector pane (if the devtools knows about its file source, a tooltip will appear).
+
+## Node.js
+
+You can use the [launch-editor](https://github.com/yyx990803/launch-editor#usage) package to setup an HTTP route with the `/__open-in-editor` path. It will receive `file` as an URL variable.
+
+## Customize request
+
+You can change the request host (default `/`) with the following code in your frontend app:
+
+```js
+if (process.env.NODE_ENV !== 'production') {
+ // App served from port 4000
+ // Webpack dev server on port 9000
+ window.VUE_DEVTOOLS_CONFIG = {
+ openInEditorHost: 'http://localhost:9000/'
+ }
+}
+```
diff --git a/vue-devtools/packages/docs/src/index.md b/vue-devtools/packages/docs/src/index.md
new file mode 100644
index 0000000000000000000000000000000000000000..8c3b7f3e0e2af6adce9a1806d0d3c132e48abc52
--- /dev/null
+++ b/vue-devtools/packages/docs/src/index.md
@@ -0,0 +1,20 @@
+---
+home: true
+sidebar: false
+heroImage: /logo.svg
+
+actionText: Install now
+actionLink: /guide/installation
+
+footer: MIT Licensed | Copyright © 2014-present Evan You, Guillaume Chau
+---
+
+## Sponsors
+
+[💚️ Become a Sponsor](https://github.com/sponsors/Akryum)
+
+
+
+
+
+
diff --git a/vue-devtools/packages/docs/src/plugin/api-reference.md b/vue-devtools/packages/docs/src/plugin/api-reference.md
new file mode 100644
index 0000000000000000000000000000000000000000..3f13ca14173937a6391068ec6a5878c4e99c56b8
--- /dev/null
+++ b/vue-devtools/packages/docs/src/plugin/api-reference.md
@@ -0,0 +1,777 @@
+# Plugin API References
+
+::: warning
+The API is only available in Vue Devtools 6+
+:::
+
+## Plugin setup
+
+### setupDevtoolsPlugin
+
+Registers a devtools plugin. Describes the plugin and provides access to the devtools API.
+
+```js
+setupDevtoolsPlugin (pluginDescriptor, setupFn)
+```
+
+The plugin descriptor is an object describing the devtools plugin to the Vue devtools user.
+
+It has the following properties:
+
+- `id`: a unique id between all possible plugins. It's recommended to use a Reverse Domain Name notation, for example: `org.vuejs.router`, or the npm package name.
+- `app`: the current application instance. The devtools is scoped to a specific application, so you have to specify on which application instance the devtools plugin is going to work.
+- `label`: the label displayed to the user. It's recommended to use a user-friendly name from your plugin, for example: `'Vue Router'`. Do not put `'devtools'` or `'plugin'` in the name, since the user will be seeing this devtools plugin while using your Vue plugin already.
+- `packageName` (optional): The `npm` package name associated with the devtools plugin, for example `'vue-router'`.
+- `homepage` (optional): URL to your documentation.
+- `logo` (optional): URL to a logo of your Vue plugin.
+- `componentStateTypes` (optional): an array of custom component state section names you are going to add to the Component inspector. If you add new state to the component inspector, you should declare their sections here so the devtools can display the plugin icon.
+- `disableAppScope` (optional): if set to `true`, the hooks registered with this plugin will not be scoped to the associated app. In that case, you might need to use the `app` payload property to check what the current app is inside each hook.
+- `disablePluginScope` (optional): if set to `true`, the hooks registered with this plugin will not be scoped to the current plugin. In that case, you might need to use the `pluginId` payload property (depending on the hook) to check what the related plugin is inside each hook.
+- `enableEarlyProxy` (optional): if set to `true`, the plugin will run even if the Vue devtools are not connected yet using a proxy of the Plugin API and a buffer queue. This is useful if you need to add timeline events before the user opens the devtools.
+- `settings` (optional): an object describing the plugin settings. Learn more about plugin settings [here](./plugins-guide.md#plugin-settings).
+
+Example:
+
+```js
+const stateType = 'routing properties'
+
+setupDevtoolsPlugin({
+ id: 'org.vuejs.router',
+ app,
+ label: 'Vue Router',
+ packageName: 'vue-router',
+ homepage: 'https://router.vuejs.org/',
+ logo: 'https://vuejs.org/images/icons/favicon-96x96.png',
+ componentStateTypes: [
+ stateType
+ ]
+}, (api) => {
+ // Use the API here
+})
+```
+
+## Component inspector
+
+### on.visitComponentTree
+
+Use this hook to add tags in the component tree.
+
+The `payload` argument:
+- `app`: app instance currently active in the devtools
+- `componentInstance`: the current component instance data in the tree
+- `treeNode`: the tree node that will be sent to the devtools
+- `filter`: the current value of the seach input above the tree in the component inspector
+
+Example:
+
+```js
+api.on.visitComponentTree((payload) => {
+ const node = payload.treeNode
+ if (node.name === 'MyApp') {
+ node.tags.push({
+ label: 'root',
+ textColor: 0x000000,
+ backgroundColor: 0xFF984F
+ })
+ }
+ else {
+ node.tags.push({
+ label: 'test',
+ textColor: 0xFFAAAA,
+ backgroundColor: 0xFFEEEE,
+ tooltip: `It's a test!`
+ })
+ }
+})
+```
+
+### on.inspectComponent
+
+Use this hook to add new information to the state of the selected component.
+
+The `payload` argument:
+- `app`: app instance currently active in the devtools
+- `componentInstance`: the current component instance data in the tree
+- `instanceData`: the state that will be sent to the devtools
+
+To add new state, you can push new fields into the `instanceData.state` array:
+
+#### Basic field
+
+- `type`: name of the section under which the field will appear
+- `key`: name of the field
+- `value`: value of the field
+- `editable` (optional): boolean to enable edition
+
+#### Custom value
+
+By default, the devtools will display your field depending on whether it's an object, an array, etc. You can customize the field display by putting a `{ _custom: {} }` object to the value.
+
+The `_custom` object has the following properties:
+
+- `type`: Displays the type of the value. Examples: `'router'`, `'component'`, `'service'`...
+- `display`: Text displayed instead of the value. Example: `'5 minutes'`
+- `tooltip`: Tooltip when hovering the value text (`display`)
+- `value`: Actual value
+- `abstract`: No value is displayed. Useful for indexes. For example, `Set` objects have abstract index child fields: `0`, `1`...
+- `readOnly`: mark this value has not editable
+- `fields`: an object of configure immediate child fields
+ - `abstract`
+- `actions`: an array of buttons to add to the field
+ - `icon`: material icon identifier
+ - `tooltip`: button tooltip
+ - `action`: function to be executed
+
+When you add new sections with the `type` property, you should declare them in the `componentStateTypes` array in the plugin descriptor when you call the `setupDevtoolsPlugin`.
+
+Example:
+
+```js
+api.on.inspectComponent((payload) => {
+ if (payload.instanceData) {
+ payload.instanceData.state.push({
+ type: stateType,
+ key: 'foo',
+ value: 'bar'
+ })
+ payload.instanceData.state.push({
+ type: stateType,
+ key: 'time',
+ value: {
+ _custom: {
+ type: null,
+ readOnly: true,
+ display: `${time}s`,
+ tooltip: 'Elapsed time',
+ value: time,
+ actions: [
+ {
+ icon: 'input',
+ tooltip: 'Log to console',
+ action: () => console.log('current time:', time)
+ }
+ ]
+ }
+ }
+ })
+ }
+})
+```
+
+### on.editComponentState
+
+If you mark a field as `editable: true`, you should also use this hook to apply the new value sent by the devtools.
+
+You have to put a condition in the callback to target only your field type:
+
+```js
+api.on.editComponentState((payload) => {
+ if (payload.type === stateType) {
+ // Edit logic here
+ }
+})
+```
+
+The `payload` argument:
+- `app`: app instance currently active in the devtools
+- `type`: the current field type
+- `path`: an array of string that represents the property edited by the user. For example, if the user edits the `myObj.myProp.hello` property, the `path` will be `['myObj', 'myProp', 'hello']`.
+- `state`: object describing the edit with those properties:
+ - `value`: new value
+ - `newKey`: string that is set if the key of the value changed, usually when it's in an object
+ - `remove`: if `true`, the value should be removed from the object or array
+- `set`: an helper function that makes it easy to apply the edit on a state object
+
+Example:
+
+```js
+api.on.editComponentState((payload) => {
+ if (payload.type === stateType) {
+ payload.set(myState)
+ }
+})
+```
+
+Here is a full example of an editable custom component field:
+
+```js
+const myState = {
+ foo: 'bar'
+}
+
+api.on.inspectComponent((payload) => {
+ if (payload.instanceData) {
+ payload.instanceData.state.push({
+ type: stateType,
+ key: 'foo',
+ value: myState.foo,
+ editable: true
+ })
+ }
+})
+
+api.on.editComponentState((payload) => {
+ if (payload.type === stateType) {
+ payload.set(myState)
+ }
+})
+```
+
+As you can see, you should use an object to hold the field value so that it can be assigned to.
+
+### notifyComponentUpdate
+
+If your state has changed, you can tell the devtools to refresh the selected component state with the `notifyComponentUpdate` method:
+
+```js
+setInterval(() => {
+ api.notifyComponentUpdate()
+}, 5000)
+```
+
+You can also pass a specific component instance:
+
+```js
+api.notifyComponentUpdate(vm)
+```
+
+## Custom inspector
+
+Custom inspectors are useful to display debugging information about your library using an inspectable tree.
+
+### addInspector
+
+This function registers a new custom inspector.
+
+The options are:
+
+- `id`: unique custom inspector id
+- `label`: label displayed in the `Inspector` sub menu
+- `icon` (optional): [Material icon code](https://material.io/resources/icons/), for example `'star'`
+- `treeFilterPlaceholder` (optional): placeholder of the filter input above the tree
+- `stateFilterPlaceholder` (optional): placeholder of the filter input in the state inspector
+- `noSelectionText` (optional): text displayed in the inspector pane when no node is selected
+- `actions`: an array of buttons to add to the header of the inspector
+ - `icon`: material icon identifier
+ - `tooltip`: button tooltip
+ - `action`: function to be executed
+- `nodeActions`: an array of buttons to add to the selected node pane
+ - `icon`: material icon identifier
+ - `tooltip`: button tooltip
+ - `action`: function to be executed
+
+Example:
+
+```js
+const INSPECTOR_ID = 'test-inspector'
+
+api.addInspector({
+ id: INSPECTOR_ID,
+ label: 'Test inspector',
+ icon: 'tab_unselected',
+ treeFilterPlaceholder: 'Search for test...',
+ actions: [
+ {
+ icon: 'star',
+ tooltip: 'Test custom action',
+ action: () => console.log('Meow! 🐱')
+ }
+ ],
+ nodeActions: [
+ {
+ icon: 'star',
+ tooltip: 'Test node custom action',
+ action: nodeId => console.log('Node action:', nodeId)
+ }
+ ]
+})
+```
+
+::: tip
+It's recommended to use a variable to put the `id`, so that you can reuse it afterwards.
+:::
+
+### on.getInspectorTree
+
+This hook is called when the devtools wants to load the tree of any custom inspector.
+
+You have to put a condition in the callback to target only your inspector:
+
+```js
+api.on.getInspectorTree((payload) => {
+ if (payload.inspectorId === 'test-inspector') {
+ // Your logic here
+ }
+})
+```
+
+The `payload` argument:
+- `app`: app instance currently active in the devtools
+- `inspectorId`: id of the current custom inspector
+- `filter`: string of the user input in the search field
+- `rootNodes`: array of root nodes of the tree you want to display in the devtools
+
+Each node can have those properties:
+- `id`: a unique node id
+- `label`: the text displayed in the tree
+- `children` (optional): an array of child nodes
+- `tags` (optional): an array of tag objects:
+ - `label`: text displayed in the tag
+ - `textColor`: text color, for example: `0x000000` for black
+ - `backgroundColor`: background color, for example: `0xffffff` for white
+ - `tooltip` (optional): HTML for a tooltip over the tag
+
+Example:
+
+```js
+api.on.getInspectorTree((payload) => {
+ if (payload.inspectorId === 'test-inspector') {
+ payload.rootNodes = [
+ {
+ id: 'root',
+ label: `Root (${time})`,
+ children: [
+ {
+ id: 'child',
+ label: `Child ${payload.filter}`,
+ tags: [
+ {
+ label: 'active',
+ textColor: 0x000000,
+ backgroundColor: 0xFF984F
+ },
+ {
+ label: 'test',
+ textColor: 0xFFFFFF,
+ backgroundColor: 0x000000
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+})
+```
+
+### on.getInspectorState
+
+This hook is called when the devtools needs to load the state for the currently selected node in a custom inspector.
+
+You have to put a condition in the callback to target only your inspector:
+
+```js
+api.on.getInspectorState((payload) => {
+ if (payload.inspectorId === 'test-inspector') {
+ // Your logic here
+ }
+})
+```
+
+The `payload` argument:
+- `app`: app instance currently active in the devtools
+- `inspectorId`: id of the current custom inspector
+- `nodeId`: id of the currently selected node
+- `state`: state sent to the devtools
+
+The state is an object, which keys are the section names in the state inspector, and the value is an array of fields:
+
+```js
+payload.state = {
+ 'section 1': [
+ // fields
+ ],
+ 'section 2': [
+ // fields
+ ]
+}
+```
+
+Each field is an object with:
+
+- `type`: name of the section under which the field will appear
+- `key`: name of the field
+- `value`: value of the field
+- `editable` (optional): boolean to enable edition
+
+You can also use a [Custom value](#custom-value).
+
+Example:
+
+```js
+api.on.getInspectorState((payload) => {
+ if (payload.inspectorId === 'test-inspector') {
+ if (payload.nodeId === 'root') {
+ payload.state = {
+ 'root info': [
+ {
+ key: 'foo',
+ value: myState.foo,
+ editable: true
+ },
+ {
+ key: 'time',
+ value: time
+ }
+ ]
+ }
+ }
+ else {
+ payload.state = {
+ 'child info': [
+ {
+ key: 'answer',
+ value: {
+ _custom: {
+ display: '42!!!',
+ value: 42,
+ tooltip: 'The answer'
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+})
+```
+
+### on.editInspectorState
+
+If you mark a field as `editable: true`, you should also use this hook to apply the new value sent by the devtools.
+
+You have to put a condition in the callback to target only your inspector:
+
+```js
+api.on.editInspectorState((payload) => {
+ if (payload.inspectorId === 'test-inspector') {
+ // Edit logic here
+ }
+})
+```
+
+The `payload` argument:
+- `app`: app instance currently active in the devtools
+- `inspectorId`: id of the current custom inspector
+- `nodeId`: id of the currently selected node
+- `type`: the current field type
+- `path`: an array of string that represents the property edited by the user. For example, if the user edits the `myObj.myProp.hello` property, the `path` will be `['myObj', 'myProp', 'hello']`.
+- `state`: object describing the edit with those properties:
+ - `value`: new value
+ - `newKey`: string that is set if the key of the value changed, usually when it's in an object
+ - `remove`: if `true`, the value should be removed from the object or array
+- `set`: an helper function that makes it easy to apply the edit on a state object
+
+Example:
+
+```js
+api.on.editInspectorState((payload) => {
+ if (payload.inspectorId === 'test-inspector') {
+ if (payload.nodeId === 'root') {
+ payload.set(myState)
+ }
+ }
+})
+```
+
+### sendInspectorTree
+
+If you need to update the tree to the user, call this function to ask for a refresh.
+
+Example:
+
+```js
+setInterval(() => {
+ api.sendInspectorTree('test-inspector')
+}, 5000)
+```
+
+### sendInspectorState
+
+If you need to update the currently selected node state to the user, call this function to ask for a refresh.
+
+Example:
+
+```js
+setInterval(() => {
+ api.sendInspectorState('test-inspector')
+}, 5000)
+```
+
+### selectInspectorNode
+
+Select a specific node in the inspector tree. The arguments are:
+
+- `inspectorId`: the id of your inspector
+- `nodeId`: the id of the node to be selected
+
+Example:
+
+```js
+api.selectInspectorNode('test-inspector', 'some-node-id')
+```
+
+## Timeline
+
+### now
+
+Returns the current time with the maximum available precision.
+
+```js
+api.now()
+```
+
+### addTimelineLayer
+
+Register a new timeline layer with this method. The options are:
+- `id`: unique id of the layer. It's recommended to use a variable to store it.
+- `label`: text displayed in the layer list
+- `color`: color of the layer background and event graphics
+- `skipScreenshots` (optional): don't trigger a screenshot for the layer events
+- `groupsOnly` (optional): only display groups of events (they will be drawn as rectangles)
+- `ignoreNoDurationGroups` (optional): skip groups with no duration (useful when `groupsOnly` is `true`)
+
+Example:
+
+```js
+api.addTimelineLayer({
+ id: 'test-layer',
+ label: 'Test layer',
+ color: 0x92A2BF
+})
+```
+
+### addTimelineEvent
+
+Use this function to send a new event on the timeline.
+- `layerId`: id of the layer
+- `event`: event object
+ - `time`: time in millisecond when the event happened
+ - `data`: state displayed when selecting the event
+ - `title` (optional): text displayed in the event list
+ - `subtitle` (optional): secondary text displayed in the event list
+ - `logType` (optional): either `'default'`, `'warning'` or `'error'`
+ - `meta` (optional): object where you can store metadata about the object that will not be displayed when it's selected
+ - `groupId` (optional): id used to group multiple event together
+
+Example:
+
+```js
+api.addTimelineEvent({
+ layerId: 'test-layer',
+ event: {
+ time: api.now(),
+ data: {
+ info: 'window.keyup',
+ key: event.key
+ },
+ groupId: event.key,
+ title: 'Group test',
+ meta: {
+ foo: 'bar'
+ }
+ }
+})
+```
+
+### on.inspectTimelineEvent
+
+This hook is called when a timline event is selected. It's useful if you want to send additional information to the devtools in a lazy way.
+
+You have to put a condition in the callback to target only your timeline layer:
+
+```js
+api.on.inspectTimelineEvent((payload) => {
+ if (payload.layerId === 'test-layer') {
+ // Your logic here
+ }
+})
+```
+
+Example:
+
+```js
+api.on.inspectTimelineEvent((payload) => {
+ if (payload.layerId === 'test-layer') {
+ // Async operation example
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ payload.data = {
+ ...payload.data,
+ hey: 'hello'
+ }
+ resolve()
+ }, 1000)
+ })
+ }
+})
+```
+
+### on.timelineCleared
+
+This hook is called when the timeline is cleared by the user. Note that clearing the timeline affects all apps and layers simultaneously.
+
+```js
+api.on.timelineCleared(() => {
+ console.log('timeline is cleared!')
+})
+```
+
+## Settings
+
+Plugin settings allow the user to customize the plugin behavior. Learn more about plugin settings [here](./plugins-guide.md#plugin-settings).
+
+### getSettings
+
+Get the current plugin settings.
+
+Example:
+
+```js
+api.getSettings()
+```
+
+### on.setPluginSettings
+
+Hook called when the user changes the plugin settings.
+
+Payload properties:
+
+- `key`: settings item
+- `newValue`: new value for the changed settings
+- `oldValue`: its old value (deep clone)
+- `settings`: the whole current settings state object
+
+```js
+// Plugin settings change
+api.on.setPluginSettings((payload) => {
+ console.log(
+ 'plugin settings changed',
+ payload.settings,
+ // Info about the change
+ payload.key,
+ payload.newValue,
+ payload.oldValue
+ )
+})
+```
+
+## Utilities
+
+### getComponentInstances
+
+Component instances on the Vue app.
+- `app`: the target Vue app instance
+
+Example:
+
+```js
+let componentInstances = []
+
+api.on.getInspectorTree(async (payload) => {
+ if (payload.inspectorId === 'test-inspector') { // e.g. custom inspector
+ componentInstances = await api.getComponentInstances(app)
+ for (const instance of instances) {
+ payload.rootNodes.push({
+ id: instance.uid.toString(),
+ label: `Component ${instance.uid}`
+ })
+ }
+
+ // something todo ...
+ }
+})
+```
+
+### getComponentBounds
+
+Computes the component bounds on the page.
+
+Example:
+
+```js
+api.on.inspectComponent(async (payload) => {
+ if (payload.instanceData) {
+ const bounds = await api.getComponentBounds(payload.componentInstance)
+ payload.instanceData.state.push({
+ type: stateType,
+ key: 'bounds',
+ value: bounds
+ ? {
+ left: bounds.left,
+ top: bounds.top,
+ width: bounds.width,
+ height: bounds.height
+ }
+ : null
+ })
+ }
+})
+```
+
+### getComponentName
+
+Retrieves the component name.
+
+Example:
+
+```js
+api.on.inspectComponent(async (payload) => {
+ if (payload.instanceData) {
+ const componentName = await api.getComponentName(payload.componentInstance)
+ payload.instanceData.state.push({
+ type: stateType,
+ key: 'component name',
+ value: componentName
+ })
+ }
+})
+```
+
+### highlightElement
+
+Highlight the element of the component.
+- `instance`: the target component instance
+
+Example:
+
+```js
+const componentInstances = [] // keeped component instance of the Vue app (e.g. `getComponentInstances`)
+
+api.on.getInspectorState((payload) => {
+ if (payload.inspectorId === 'test-inspector') { // e.g. custom inspector
+ // find component instance from custom inspector node
+ const instance = componentInstances.find(instance => instance.uid.toString() === payload.nodeId)
+
+ if (instance) {
+ api.highlightElement(instance)
+ }
+
+ // something todo ...
+ }
+})
+```
+
+### unhighlightElement
+
+Unhighlight the element.
+- `instance`: the target component instance
+
+Example:
+
+```js
+const componentInstances = [] // keeped component instance of the Vue app (e.g. `getComponentInstances`)
+
+api.on.getInspectorState((payload) => {
+ if (payload.inspectorId === 'test-inspector') { // e.g. custom inspector
+ // find component instance from custom inspector node
+ const instance = componentInstances.find(instance => instance.uid.toString() === payload.nodeId)
+
+ if (instance) {
+ api.unhighlightElement(instance)
+ }
+
+ // something todo ...
+ }
+})
+```
diff --git a/vue-devtools/packages/docs/src/plugin/plugins-guide.md b/vue-devtools/packages/docs/src/plugin/plugins-guide.md
new file mode 100644
index 0000000000000000000000000000000000000000..424e49b4a8f73a9e1873bf1303a305318eb6b1b0
--- /dev/null
+++ b/vue-devtools/packages/docs/src/plugin/plugins-guide.md
@@ -0,0 +1,1273 @@
+---
+sidebarDepth: 5
+---
+
+# Plugin Development Guide
+
+::: warning Notice
+The API is only available in Vue Devtools 6+
+:::
+
+## Architecture
+
+A Vue Devtools Plugin is registered from your Vue package code in the user app. It interacts with the Vue Devtools Backend, *via* [the public API](./api-reference.md). The Backend is a script injected to the web page when Vue Devtools are opened by the user - it handles registering Vue applications and communicating with the Vue Devtools Frontend. The Frontend is the Vue application displayed in the browser devtools pane. The Hook is a global variable added to the page so that the Vue application and your plugin can send messages to the Backend.
+
+There are 3 main API categories:
+- **Components Inspector**: your plugin can add more information to the component tree and state.
+- **Custom Inspectors**: you can add new inspectors to display any kind of state. For example: routes, store current state...
+- **Timeline**: you can add custom layers and send events.
+
+Using the API, you can show information to the user and improve the app debugging experience. Official libraries like `vue-router` and `vuex` already use this API!
+
+### Architecture schema
+
+
+
+## Examples
+
+- [Vue 3 plugin](https://github.com/Akryum/vue3-devtools-plugin-example)
+- [Vue 2 plugin](https://github.com/Akryum/vue2-devtools-plugin-example)
+
+## Setup
+
+In your package, install `@vue/devtools-api` as a dependency:
+
+```bash
+yarn add @vue/devtools-api
+```
+
+This package will let you register a new Vue Devtools Plugin from your code and comes with full TypeScript typings.
+
+Your `package.json` file should look similar to this:
+
+```json
+{
+ "name": "my-awesome-plugin",
+ "version": "0.0.0",
+ "main": "dist/index.js",
+ "dependencies": {
+ "@vue/devtools-api": "^6.0.0-beta.14"
+ },
+ "peerDependencies": {
+ "vue": "^3.1.0"
+ },
+ "devDependencies": {
+ "vue": "^3.1.0"
+ }
+}
+```
+
+It's a good idea to also specify `vue` as a peer dependency to inform the user which version of Vue your package is compatible with.
+
+### TypeScript
+
+If you are using TS, your `package.json` file should look similar to this:
+
+```json
+{
+ "name": "my-awesome-plugin",
+ "version": "0.0.0",
+ "main": "dist/index.js",
+ "scripts": {
+ "dev": "tsc --watch -d",
+ "build": "tsc -d"
+ },
+ "dependencies": {
+ "@vue/devtools-api": "^6.0.0-beta.14"
+ },
+ "peerDependencies": {
+ "vue": "^3.1.0"
+ },
+ "devDependencies": {
+ "@types/node": "^20.11.16",
+ "typescript": "^5.3.3",
+ "vue": "^3.1.0"
+ }
+}
+```
+
+Here is an example `tsconfig.json` file to put next to the `package.json` file:
+
+```json
+{
+ "include": [
+ "src/global.d.ts",
+ "src/**/*.ts",
+ "__tests__/**/*.ts"
+ ],
+ "compilerOptions": {
+ "outDir": "dist",
+ "sourceMap": false,
+
+ "target": "esnext",
+ "module": "esnext",
+ "moduleResolution": "node",
+ "allowJs": false,
+ "skipLibCheck": true,
+
+ "noUnusedLocals": true,
+ "strictNullChecks": true,
+ "noImplicitAny": true,
+ "noImplicitThis": true,
+ "noImplicitReturns": false,
+ "strict": true,
+ "isolatedModules": true,
+
+ "experimentalDecorators": true,
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "removeComments": false,
+ "jsx": "preserve",
+ "lib": [
+ "esnext",
+ "dom"
+ ],
+ "types": [
+ "node"
+ ]
+ }
+}
+```
+
+### Rollup
+
+[Rollup](https://rollupjs.org/) is a general-purpose bundler. You can use it to compile your package for easier consumption. It's also very handy if you have `.vue` files to compile!
+
+```bash
+yarn add -D rollup rollup-plugin-vue @rollup/plugin-commonjs @rollup/plugin-node-resolve @rollup/plugin-replace rollup-plugin-terser pascalcase rimraf
+```
+
+::: tip Notice about the packages
+- `rollup-plugin-vue` compiles the `.vue` files.
+- `@rollup/plugin-commonjs` converts CommonJS modules to ES2015 modules.
+- `@rollup/plugin-node-resolve` locates and bundles third-party dependencies in `node_modules`.
+- `@rollup/plugin-replace` allow us to replace some source code text like `process.env.NODE_ENV` with the values we want at build time.
+- `rollup-plugin-terser` minimizes the output for production.
+- `pascalcase` is used to convert your package name (from `package.json`) into Pascal case, for example `my-plugin` to `MyPlugin`.
+- `rimraf` is useful to clear the `dist` folder before building.
+:::
+
+#### Rollup config
+
+Create a `rollup.config.js` file next to the `package.json` file:
+
+[See example](https://gist.github.com/Akryum/b200b92689c6d7e3bb3871da906be01e)
+
+#### Rollup package
+
+Add the main fields, `exports` and `scripts` to your `package.json`:
+
+```json
+{
+ "name": "my-plugin",
+ "version": "0.0.0",
+ "description": "A demo Vue 3 plugin with devtools integration",
+ "author": {
+ "name": "Guillaume Chau",
+ "email": "guillaume.b.chau@gmail.com"
+ },
+ "main": "dist/my-plugin.cjs.js",
+ "module": "dist/my-plugin.esm-bundler.js",
+ "unpkg": "dist/my-plugin.global.js",
+ "jsdelivr": "dist/my-plugin.global.js",
+ "exports": {
+ ".": {
+ "require": "./dist/my-plugin.cjs.js",
+ "browser": "./dist/my-plugin.esm-browser.js",
+ "import": "./dist/my-plugin.esm-bundler.js",
+ "module": "./dist/my-plugin.esm-bundler.js"
+ },
+ "./package.json": "./package.json"
+ },
+ "sideEffects": false,
+ "scripts": {
+ "build": "rimraf dist && rollup -c rollup.config.js"
+ }
+ // ...
+}
+```
+
+Don't forget to replace `my-plugin` with your package name.
+
+You can now use the `build` script to compile the package:
+
+```bash
+yarn build
+```
+
+#### Rollup with TypeScript
+
+Install the Rollup TS plugin:
+
+```bash
+yarn add -D rollup-plugin-typescript2
+```
+
+Modify the Rollup config to compile the TS files:
+
+[See example](https://gist.github.com/Akryum/cb0a396904169bd55ddf964e3b20452a)
+
+And add the `types` field to your `package.json` file:
+
+```json{13}
+{
+ "name": "my-plugin",
+ "version": "0.0.0",
+ "description": "A demo Vue 3 plugin with devtools integration",
+ "author": {
+ "name": "Guillaume Chau",
+ "email": "guillaume.b.chau@gmail.com"
+ },
+ "main": "dist/my-plugin.cjs.js",
+ "module": "dist/my-plugin.esm-bundler.js",
+ "unpkg": "dist/my-plugin.global.js",
+ "jsdelivr": "dist/my-plugin.global.js",
+ "types": "dist/index.d.ts",
+ "exports": {
+ ".": {
+ "require": "./dist/my-plugin.cjs.js",
+ "browser": "./dist/my-plugin.esm-browser.js",
+ "import": "./dist/my-plugin.esm-bundler.js",
+ "module": "./dist/my-plugin.esm-bundler.js"
+ },
+ "./package.json": "./package.json"
+ },
+ "sideEffects": false,
+ "scripts": {
+ "build": "rimraf dist && rollup -c rollup.config.js"
+ }
+ ...
+}
+```
+
+See [TypeScript](#typescript) for a `tsconfig.json` example.
+
+
+
+## Registering your plugin
+
+Create a new `devtools.js` file in your source folder.
+
+### Plugin setup
+
+We are going to import [`setupDevtoolsPlugin`](./api-reference.md#setupdevtoolsplugin) from the `@vue/devtools-api` package:
+
+```js
+import { setupDevtoolsPlugin } from '@vue/devtools-api'
+```
+
+Then we export a function to setup our Vue Devtools plugin:
+
+```js
+export function setupDevtools() {
+ setupDevtoolsPlugin({ /* Options... */}, (api) => {
+ // Logic...
+ })
+}
+```
+
+Add the plugin options in the first argument:
+
+```js{2-5}
+setupDevtoolsPlugin({
+ id: 'my-awesome-devtools-plugin',
+ label: 'My Awesome Plugin',
+ packageName: 'my-awesome-plugin',
+ homepage: 'https://vuejs.org'
+}, api => {
+ // Logic...
+})
+```
+
+Every plugin is bound to a Vue application. You need to pass the user application to `setupDevtoolsPlugin` - the same that your plugin `install` method gets as the first argument.
+
+```js{1,7}
+export function setupDevtools (app) {
+ setupDevtoolsPlugin({
+ id: 'my-awesome-devtools-plugin',
+ label: 'My Awesome Plugin',
+ packageName: 'my-awesome-plugin',
+ homepage: 'https://vuejs.org',
+ app
+ }, api => {
+ // Logic...
+ })
+}
+```
+
+The second argument of `setupDevtoolsPlugin` is a callback which will get the Vue Devtools API as the first argument:
+
+```js{5-7}
+export function setupDevtools (app) {
+ setupDevtoolsPlugin({
+ id: 'my-awesome-devtools-plugin',
+ // ...
+ }, api => {
+ // Use the API here...
+ })
+}
+```
+
+We can now import and use our `setupDevtools` function in our Vue plugin:
+
+```js
+import { setupDevtools } from './devtools'
+
+export default {
+ install(app, options = {}) {
+ // Our Vue plugin logic
+
+ setupDevtools(app)
+ }
+}
+```
+
+### Vue 2
+
+In a Vue 2 app, you need to pass the root component instance as the `app` parameter:
+
+```js
+import { setupDevtools } from './devtools'
+
+export default {
+ install(Vue) {
+ Vue.mixin({
+ beforeCreate() {
+ if (this.$options.myPlugin) {
+ setupDevtools(this)
+ }
+ }
+ })
+ }
+}
+```
+
+In the user's app:
+
+```js
+import Vue from 'vue'
+import App from './App.vue'
+import DevtoolsPlugin from './DevtoolsPlugin'
+
+Vue.use(DevtoolsPlugin)
+
+new Vue({
+ render: h => h(App),
+ myPlugin: true,
+}).$mount('#app')
+```
+
+### Plugin settings
+
+With the `settings` option, your plugin can expose some settings to the user. This can be very useful to allow some customization!
+
+All settings items must have the following properties:
+- `type` (see below)
+- `label`: a string to describe the settings item
+- `defaultValue`
+
+Available settings types:
+- `boolean`
+- `text`
+- `choice`
+ - `options`: list of objects with type `{ value: any, label: string }`
+ - `component`: (optional) can be either `'select'` (default) or `'button-group'`
+
+Example:
+
+```js
+setupDevtoolsPlugin({
+ id: 'my-awesome-devtools-plugin',
+ settings: {
+ test1: {
+ label: 'I like vue devtools',
+ type: 'boolean',
+ defaultValue: true
+ },
+ test2: {
+ label: 'Quick choice',
+ type: 'choice',
+ defaultValue: 'a',
+ options: [
+ { value: 'a', label: 'A' },
+ { value: 'b', label: 'B' },
+ { value: 'c', label: 'C' }
+ ],
+ component: 'button-group'
+ },
+ test3: {
+ label: 'Long choice',
+ type: 'choice',
+ defaultValue: 'a',
+ options: [
+ { value: 'a', label: 'A' },
+ { value: 'b', label: 'B' },
+ { value: 'c', label: 'C' },
+ { value: 'd', label: 'D' },
+ { value: 'e', label: 'E' }
+ ]
+ },
+ test4: {
+ label: 'What is your name?',
+ type: 'text',
+ defaultValue: ''
+ }
+ },
+}, (api) => {
+ // Use `api.getSettings()` to get the current settings for the plugin
+ console.log(api.getSettings())
+})
+```
+
+
+
+You can listen for changes made to the settings by the user with the [`api.on.setPluginSettings`](./api-reference.md#on-setpluginsettings) hook:
+
+```js
+api.on.setPluginSettings((payload) => {
+ // Do something...
+})
+```
+
+### Tree-shaking for production
+
+As we are going to write code only for integrating for the Vue Devtools, it would be a good idea to strip it for the production versions of our package - thus improving size and performance.
+
+By default, Vue 3 doesn't include the devtools-related code in production. [It uses](https://github.com/vuejs/vue-next/tree/master/packages/vue#bundler-build-feature-flags) the `__VUE_PROD_DEVTOOLS__` environment variable as a compile flag to force enable this code. We can use the same one for the same purpose, and we can also check for `NODE_ENV` to automatically include the devtools plugin in development.
+
+```js
+if (process.env.NODE_ENV === 'development' || __VUE_PROD_DEVTOOLS__) {
+ setupDevtools(app)
+}
+```
+
+In your build setup you should replace `process.env.NODE_ENV` and `__VUE_PROD_DEVTOOLS__` for the builds of your library that don't target bundlers. See [Rollup setup](#rollup) that includes an example usage of `@rollup/plugin-replace`.
+
+## Components
+
+The Components API allows you to:
+
+- Add tags to the components tree.
+- Display additional data in the component state inspector.
+
+### Hooks
+
+The Vue Devtools API includes **Hooks** which are available *via* `api.on`. Hooks are useful to add new debugging information to existing elements, such as components tree nodes, component state, timeline events... A new callback for a specific hook can be registered with `api.on.hookName(callback)`.
+
+Every hook expects the callback function to have those same arguments:
+- `payload` which holds the state related to the hook. It can be modified to pass back additional information.
+- `context` exposing data about the devtools
+
+Example:
+
+```js{6-8}
+export function setupDevtools (app) {
+ setupDevtoolsPlugin({
+ id: 'my-awesome-devtools-plugin',
+ // ...
+ }, api => {
+ api.on.hookNameHere((payload, context) => {
+ // Do something...
+ })
+ })
+}
+```
+
+Every hook handle asynchronous callbacks:
+
+```js{6-8}
+export function setupDevtools (app) {
+ setupDevtoolsPlugin({
+ id: 'my-awesome-devtools-plugin',
+ // ...
+ }, api => {
+ api.on.hookNameHere(async (payload, context) => {
+ await something()
+ })
+ })
+}
+```
+
+All the registered callbacks will be called sequentially including the asynchronous ones, in the order they were registered on the page.
+
+### Components tree
+
+To add tags to the components tree, we can use the [`visitComponentTree`](./api-reference.md#on-visitcomponenttree) hook:
+
+```js{6-14}
+export function setupDevtools (app) {
+ setupDevtoolsPlugin({
+ id: 'my-awesome-devtools-plugin',
+ // ...
+ }, api => {
+ api.on.visitComponentTree((payload, context) => {
+ const node = payload.treeNode
+ if (payload.componentInstance.type.meow) {
+ node.tags.push({
+ label: 'meow',
+ textColor: 0x000000,
+ backgroundColor: 0xff984f
+ })
+ }
+ })
+ })
+}
+```
+
+This example will add a `meow` tag to any component that add the `meow: true` option to its definition:
+
+```js
+export default {
+ meow: true
+}
+```
+
+Here is an example result:
+
+
+
+### Colors
+
+Colors in the Vue Devtools API are encoded as numbers instead of strings. You can use `0x` in JavaScript to write an hexadecimal value:
+
+```js
+0x000000 // black
+0xFFFFFF // white
+0xFF984F // orange
+0x41B86A // green
+```
+
+Example:
+
+```js{6-7}
+api.on.visitComponentTree((payload, context) => {
+ const node = payload.treeNode
+ if (payload.componentInstance.type.meow) {
+ node.tags.push({
+ label: 'meow',
+ textColor: 0x000000,
+ backgroundColor: 0xff984f
+ })
+ }
+})
+```
+
+### Notify a change
+
+By default the Vue Devtools will determine when to update the components tree (and thus calling the hook again). We can force a refresh with the [`api.notifyComponentUpdate`](./api-reference.md#notifycomponentupdate) function:
+
+```js
+api.notifyComponentUpdate(componentInstance)
+```
+
+That way, if we know that the tags of a specific component should be changed, we can notify the Vue Devtools and then our hook callback will be called again.
+
+### Component state
+
+Adding new data to the component state inspector can be achieved with the [`inspectComponent`](./api-reference.md#on-inspectcomponent) hook:
+
+```js
+api.on.inspectComponent((payload, context) => {
+ // ...
+})
+```
+
+Each new field should be added to the `payload.instanceData.state` array:
+
+```js{2-6,8-12}
+api.on.inspectComponent((payload, context) => {
+ payload.instanceData.state.push({
+ type: 'My Awesome Plugin state',
+ key: '$hello',
+ value: data.message
+ })
+
+ payload.instanceData.state.push({
+ type: 'My Awesome Plugin state',
+ key: 'time counter',
+ value: data.counter
+ })
+})
+```
+
+Notice how we are passing some data to the Vue Devtools plugin from our library with the `data` argument of `setupDevtools` (see below).
+
+The `type` will be used to create a new section in the state inspector. It is recommended to use a variable:
+
+```js{1,10,16}
+const stateType = 'My Awesome Plugin state'
+
+export function setupDevtools (app, data) {
+ setupDevtoolsPlugin({
+ id: 'my-awesome-devtools-plugin',
+ // ...
+ }, api => {
+ api.on.inspectComponent((payload, context) => {
+ payload.instanceData.state.push({
+ type: stateType,
+ key: '$hello',
+ value: data.message
+ })
+
+ payload.instanceData.state.push({
+ type: stateType,
+ key: 'time counter',
+ value: data.counter
+ })
+ })
+ })
+}
+```
+
+Then, use this variable to declare your data type in the Vue Devtools plugin options using `componentStateTypes`:
+
+```js{7-9}
+export function setupDevtools (app) {
+ setupDevtoolsPlugin({
+ id: 'my-awesome-devtools-plugin',
+ label: 'My Awesome Plugin',
+ packageName: 'my-awesome-plugin',
+ homepage: 'https://vuejs.org',
+ componentStateTypes: [
+ stateType
+ ],
+ app
+ }, api => {
+ // ...
+ })
+}
+```
+
+Here is an example result:
+
+
+
+You can again use `notifyComponentUpdate` to force a state refresh of the current component if you don't pass any argument:
+
+```js
+api.notifyComponentUpdate()
+```
+
+### Editing component state
+
+You can mark some of your state fields as `editable` to allow editing by the user:
+
+```js
+payload.instanceData.state.push({
+ type: stateType,
+ key: '$hello',
+ value: data.message,
+ editable: true
+})
+```
+
+You can then handle the edition submit with the [`editComponentState`](./api-reference.md#on-editcomponentstate) hook:
+
+```js
+api.on.editComponentState((payload) => {
+ // ...
+})
+```
+
+Then, you have to check if the field being edited is coming from your plugin with `payload.type`:
+
+```js{2}
+api.on.editComponentState(payload => {
+ if (payload.type === stateType) {
+ // ...
+ }
+})
+```
+
+This way we don't do anything if the user is editing something else (like data properties).
+
+An edited field can be modified in the following ways:
+
+- assigning a new value,
+- adding a new property (object) or item (array),
+- removing a property or item.
+
+You can then use the `payload.set` helper function to apply the edition. The argument to `payload.set` should be the object holding our editable state:
+
+```js{3}
+api.on.editComponentState(payload => {
+ if (payload.type === stateType) {
+ payload.set(data)
+ }
+})
+```
+
+In this example, we execute `payload.set(data)` because we are sending the `data.message` editable state:
+
+```js{4}
+payload.instanceData.state.push({
+ type: stateType,
+ key: '$hello',
+ value: data.message,
+ editable: true
+})
+```
+
+You can also use a separate object to hold your editable state ([example](./api-reference.md#on-editcomponentstate)).
+
+## Custom inspector
+
+The Vue Devtools only have one inspector by default: the Components inspector. Vue Devtools plugins can introduce new inspectors alongside it to display more debugging information.
+
+To setup a custom inspector, your plugin must:
+
+1. Register the custom inspector with `addInspector`.
+2. Handle the `getInspectorTree` hook to populate the inspector tree (on the left or top of the devtools).
+3. Handle the `getInspectorState` hook to send state (on the right or bottom of the devtools).
+
+### Register the custom inspector
+
+Let's start by regiustering our custom inspector with [`addInspector`](./api-reference.md#addinspector):
+
+```js
+api.addInspector({
+ id: 'my-awesome-plugin',
+ label: 'Awesome!',
+ icon: 'pets',
+})
+```
+
+It is recommended to use a variable to store the inspector id as it will be needed in the hooks later:
+
+```js{1,9}
+const inspectorId = 'my-awesome-plugin'
+
+export function setupDevtools (app, data) {
+ setupDevtoolsPlugin({
+ id: 'my-awesome-devtools-plugin',
+ // ...
+ }, api => {
+ api.addInspector({
+ id: inspectorId,
+ label: 'Awesome!',
+ icon: 'pets',
+ })
+ })
+}
+```
+
+You can use any [Material Icon](https://fonts.google.com/icons) code for the icon, for example `note_add` or `drag_indicator`.
+
+Here is an example result:
+
+
+
+### Send inspector tree
+
+With the [`getInspectorTree`](./api-reference.md#on-getinspectortree), we can display a tree of nodes in our inspector:
+
+```js
+api.on.getInspectorTree((payload, context) => {
+ // ...
+})
+```
+
+But before that, we need to check if hook is called for the correct inspector (ours):
+
+```js{2}
+api.on.getInspectorTree((payload, context) => {
+ if (payload.inspectorId === inspectorId) {
+ // ...
+ }
+})
+```
+
+We can then put the nodes tree into `payload.rootNodes`:
+
+```js{3-29}
+api.on.getInspectorTree((payload, context) => {
+ if (payload.inspectorId === inspectorId) {
+ payload.rootNodes = [
+ {
+ id: 'root',
+ label: 'Awesome root',
+ children: [
+ {
+ id: 'child-1',
+ label: 'Child 1',
+ tags: [
+ {
+ label: 'awesome',
+ textColor: 0xffffff,
+ backgroundColor: 0x000000
+ }
+ ]
+ },
+ {
+ id: 'child-2',
+ label: 'Child 2'
+ }
+ ]
+ },
+ {
+ id: 'root2',
+ label: 'Amazing root'
+ }
+ ]
+ }
+})
+```
+
+Here is an example result:
+
+
+
+### Send the inspector state
+
+Use the [`getInspectorState`](./api-reference.md#on-getinspectorstate) hook to send the state depending on the selected node (check `payload.nodeId`):
+
+```js
+api.on.getInspectorState((payload, context) => {
+ if (payload.inspectorId === inspectorId) {
+ if (payload.nodeId === 'child-1') {
+ payload.state = {
+ 'my section': [
+ {
+ key: 'cat',
+ value: 'meow',
+ }
+ ]
+ }
+ }
+ else if (payload.nodeId === 'child-2') {
+ payload.state = {
+ 'my section': [
+ {
+ key: 'dog',
+ value: 'waf',
+ }
+ ]
+ }
+ }
+ }
+})
+```
+
+Don't forget to check if the inspector is the right one with `payload.inspectorId`!
+
+Here is an example result when selecting "Child 1":
+
+
+
+### Refresh the inspector
+
+The Vue Devtools will not automatically refresh your custom inspector. To send updates, you have two different available functions:
+
+- [`sendInspectorTree`](./api-reference.md#sendinspectortree) to refresh the nodes tree,
+- [`sendInspectorState`](./api-reference.md#sendinspectorstate) to refersh the state inspector.
+
+Example:
+
+```js
+// Update tree
+api.sendInspectorTree(inspectorId)
+
+// Update state
+api.sendInspectorState(inspectorId)
+```
+
+Calling those functions will call the `getInspectorTree` and `getInspectorState` hooks respectively.
+
+## Timeline
+
+The Vue Devtools comes with a few built-in layers on the Timeline, such as the Mouse & Keyboard events, the Component events and the Performance flamechart. You can add custom Timeline layers with the following steps:
+
+1. Register the layer with `addTimelineLayer`.
+2. Send events with `addTimelineEvent`.
+
+### Register a layer
+
+Use the [`addTimelineLayer`](./api-reference.md#addtimelinelayer) function to register your custom Timeline layer:
+
+```js{1,8-12}
+const timelineLayerId = 'my-awesome-plugin'
+
+export function setupDevtools (app, data) {
+ setupDevtoolsPlugin({
+ id: 'my-awesome-devtools-plugin',
+ // ...
+ }, api => {
+ api.addTimelineLayer({
+ id: timelineLayerId,
+ color: 0xff984f,
+ label: 'Awesome!'
+ })
+ })
+}
+```
+
+Here is an example result:
+
+
+
+### Send an event
+
+Adding new events is done with the [`addTimelineEvent`](./api-reference.md#addtimelineevent) function:
+
+```js{2-11}
+window.addEventListener('click', event => {
+ api.addTimelineEvent({
+ layerId: timelineLayerId,
+ event: {
+ time: api.now(),
+ data: {
+ mouseX: event.clientX,
+ mouseY: event.clientY
+ }
+ }
+ })
+})
+```
+
+You can set the `enableEarlyProxy` plugin option to `true` to be able to send timeline events before the Vue devtools are opened and connected:
+
+```js{2-5}
+setupDevtoolsPlugin({
+ id: 'my-awesome-devtools-plugin',
+ app,
+ enableEarlyProxy: true
+}, api => {
+ // `api` will be a proxy waiting for the real API to be available
+})
+```
+
+### Event group
+
+You can group events together. It will display them inside a pill-shaped rectangle, and will display the total duration of the group in the event inspector.
+
+Set the `groupId` option on the `event` with an identical value to create a group. Here is an example of a group with 3 events:
+
+```js
+const groupId = 'group-1'
+
+devtoolsApi.addTimelineEvent({
+ layerId: timelineLayerId,
+ event: {
+ time: api.now(),
+ data: {
+ label: 'group test'
+ },
+ title: 'group test',
+ groupId
+ }
+})
+
+devtoolsApi.addTimelineEvent({
+ layerId: timelineLayerId,
+ event: {
+ time: api.now() + 10,
+ data: {
+ label: 'group test (event 2)',
+ },
+ title: 'group test',
+ groupId
+ }
+})
+
+devtoolsApi.addTimelineEvent({
+ layerId: timelineLayerId,
+ event: {
+ time: api.now() + 20,
+ data: {
+ label: 'group test (event 3)',
+ },
+ title: 'group test',
+ groupId
+ }
+})
+```
+
+Here is the result on the timeline with the first event of the group selected:
+
+
+
+And the event inspector view with the "Group" tab:
+
+
+
+Notice the "group info" section with additional information about the group.
+
+### Events from the package
+
+Let's use the `addTimelineEvent` API to track an asynchronous method expose by our Vue plugin. We will call it `$doSomething`:
+
+```js{5-15}
+import { setupDevtools } from './devtools'
+
+export default {
+ install (app, options = {}) {
+ app.mixin({
+ methods: {
+ $doSomething () {
+ return new Promise(resolve => {
+ setTimeout(() => {
+ resolve('done')
+ }, 1000)
+ })
+ }
+ }
+ })
+
+ if (process.env.NODE_ENV === 'development' || __VUE_PROD_DEVTOOLS__) {
+ setupDevtools(app, data)
+ }
+ }
+}
+```
+
+We can now call this method from any component in the user application:
+
+```js
+this.$doSomething()
+```
+
+We would like to track this method from our library code, so we need to return a set of helper functions from our `setupDevtools` function. The `devtoolsApi` variable will hold the Vue Devtools API and the `devtools` variable will be an object with helper functions, which we will return:
+
+```js{2,4-6,12,17}
+export function setupDevtools (app, data) {
+ let devtoolsApi
+
+ const devtools = {
+ // Our helpers here
+ }
+
+ setupDevtoolsPlugin({
+ id: 'my-awesome-devtools-plugin',
+ // ...
+ }, api => {
+ devtoolsApi = api
+
+ // ...
+ })
+
+ return devtools
+}
+```
+
+Back in our library code, we can create a `devtools` variable to retrieve the result of `setupDevtools`, i.e. the object that will contain our helper functions:
+
+```js{5,12}
+import { setupDevtools } from './devtools'
+
+export default {
+ install (app, options = {}) {
+ let devtools
+
+ app.mixin({
+ // ...
+ })
+
+ if (process.env.NODE_ENV === 'development' || __VUE_PROD_DEVTOOLS__) {
+ devtools = setupDevtools(app)
+ }
+ }
+}
+```
+
+Let's implement a `trackStart` helper function to create one event when we want to start tracking a call, and another event when the call is finished:
+
+```js{3,6-37}
+export function setupDevtools (app, data) {
+ let devtoolsApi
+ let trackId = 0
+
+ const devtools = {
+ trackStart: (label: string) => {
+ const groupId = 'track' + trackId++
+
+ // Start
+ devtoolsApi.addTimelineEvent({
+ layerId: timelineLayerId,
+ event: {
+ time: api.now(),
+ data: {
+ label
+ },
+ title: label,
+ groupId
+ }
+ })
+
+ return () => {
+ // End
+ devtoolsApi.addTimelineEvent({
+ layerId: timelineLayerId,
+ event: {
+ time: api.now(),
+ data: {
+ label,
+ done: true
+ },
+ title: label,
+ groupId
+ }
+ })
+ }
+ }
+ }
+
+ setupDevtoolsPlugin({
+ id: 'my-awesome-devtools-plugin',
+ // ...
+ }, api => {
+ devtoolsApi = api
+
+ // ...
+ })
+
+ return devtools
+}
+```
+
+The `trackId` is used to generate a unique group ID for each time we are going to call `startTrack`. By using the same ID, we will create a group with the two events, even if they are not both created at the same time.
+
+We can use this `trackStart` helper function like this:
+
+```js
+const trackEnd = devtools.trackStart('some-label')
+// Later
+trackEnd()
+```
+
+We can now use this `trackStart` function in our library code:
+
+```js{6,9}
+let devtools
+
+app.mixin({
+ methods: {
+ $doSomething () {
+ const trackEnd = devtools ? devtools.trackStart('$doSomething') : null
+ return new Promise(resolve => {
+ setTimeout(() => {
+ if (trackEnd) trackEnd()
+ resolve('done')
+ }, 1000)
+ })
+ }
+ }
+})
+
+if (process.env.NODE_ENV === 'development' || __VUE_PROD_DEVTOOLS__) {
+ devtools = setupDevtools(app, data)
+}
+```
+
+::: warning
+We must be careful of checking if our `devtools` variable is defined, because we strip the devtools code out in production! See [Tree-shaking for production](#tree-shaking-for-production).
+:::
+
+Here is an example result:
+
+
+
+And the event inspector:
+
+
+
+---
+
+Thank you for following the Vue Devtools Plugin development guide! You can find more detailed descriptions of the API in the [API Reference](./api-reference.md). Happy building! 😸
diff --git a/vue-devtools/packages/docs/src/public/favicon.png b/vue-devtools/packages/docs/src/public/favicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..8d28c87285409ff468065716f4addc909f28865a
Binary files /dev/null and b/vue-devtools/packages/docs/src/public/favicon.png differ
diff --git a/vue-devtools/packages/docs/src/public/favicon.svg b/vue-devtools/packages/docs/src/public/favicon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4ee2e82507b0bf83f7b3843db2616d2eee8b330f
--- /dev/null
+++ b/vue-devtools/packages/docs/src/public/favicon.svg
@@ -0,0 +1,41 @@
+
+
diff --git a/vue-devtools/packages/docs/src/public/logo-chrome.svg b/vue-devtools/packages/docs/src/public/logo-chrome.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c40feec734250bd185a3f877d20167f4ccfaf01c
--- /dev/null
+++ b/vue-devtools/packages/docs/src/public/logo-chrome.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vue-devtools/packages/docs/src/public/logo-edge.png b/vue-devtools/packages/docs/src/public/logo-edge.png
new file mode 100644
index 0000000000000000000000000000000000000000..fc7e5d615013707bf8a182cf48eca43eb46d60c3
--- /dev/null
+++ b/vue-devtools/packages/docs/src/public/logo-edge.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bfed419ac8e93983548b1df41c7726d4e5551d95dbba5a11aa59d54b24acce18
+size 144710
diff --git a/vue-devtools/packages/docs/src/public/logo-electron.svg b/vue-devtools/packages/docs/src/public/logo-electron.svg
new file mode 100644
index 0000000000000000000000000000000000000000..dc81c99d2cf5b8b49a4726fdafdbe58a43ceb38d
--- /dev/null
+++ b/vue-devtools/packages/docs/src/public/logo-electron.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vue-devtools/packages/docs/src/public/logo-firefox.svg b/vue-devtools/packages/docs/src/public/logo-firefox.svg
new file mode 100644
index 0000000000000000000000000000000000000000..138627426077f5b7ee67810d1ce5f4aba74d7fb1
--- /dev/null
+++ b/vue-devtools/packages/docs/src/public/logo-firefox.svg
@@ -0,0 +1,111 @@
+
+
+
\ No newline at end of file
diff --git a/vue-devtools/packages/docs/src/public/logo-header.svg b/vue-devtools/packages/docs/src/public/logo-header.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a4a3a7bd914f72ccfe8bc15ba08cb94ad7ae35dd
--- /dev/null
+++ b/vue-devtools/packages/docs/src/public/logo-header.svg
@@ -0,0 +1,25 @@
+
+
diff --git a/vue-devtools/packages/docs/src/public/logo.png b/vue-devtools/packages/docs/src/public/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..9fa4c9ddeae352f5a4ce79e6e907696982c9cea2
Binary files /dev/null and b/vue-devtools/packages/docs/src/public/logo.png differ
diff --git a/vue-devtools/packages/docs/src/public/logo.svg b/vue-devtools/packages/docs/src/public/logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..3f2f52f8bd3f0cd89aba471d35d1bdeca2ec8010
--- /dev/null
+++ b/vue-devtools/packages/docs/src/public/logo.svg
@@ -0,0 +1,37 @@
+
+
diff --git a/vue-devtools/packages/docs/src/release.md b/vue-devtools/packages/docs/src/release.md
new file mode 100644
index 0000000000000000000000000000000000000000..533358b0ec91da429d4f456805ba46282ad3a429
--- /dev/null
+++ b/vue-devtools/packages/docs/src/release.md
@@ -0,0 +1,32 @@
+# Releasing Devtools
+
+> This is for maintainers only.
+
+## Pre-requisites
+
+1. Make sure you have publishing rights to the `@vue/devtools` and `@vue/devtools-api` npm packages (check with `npm owner ls @vue/devtools`). If not, ping @yyx990803 for publishing permission.
+
+2. Sign up and create [API keys for Firefox Addons](https://addons.mozilla.org/developers/addon/api/key/). Create `.amo.env.json` in project root with the keys:
+
+ ```json
+ {
+ "apiKey": "...",
+ "apiSecret": "..."
+ }
+ ```
+
+3. Run `npm run release:beta`.
+
+ If it completes without error, it should have published the necessary npm packages.
+
+ In addition, this should create the following files:
+
+ - `dist/chrome.zip`
+
+ This is the packed chrome extension which should be uploaded via [Chrome Web Store developer dashboard](https://chrome.google.com/webstore/devconsole). Note the items are under the `vuejs-dev` publisher group. We current have two extensions, one for beta (currently Vue 3 only) and one for stable (Vue 2 only). We will eventually replace the stable with this branch once it supports both Vue 2 and Vue 3, but for now the Vue 3 supporting version should be published under the beta channel.
+
+ - `distvue.js_devtools-x.x.x.zip`
+
+ Similarly, the stable version of the Firefox Addon can be updated [here](https://addons.mozilla.org/en-US/developers/addon/vue-js-devtools/edit). But before then, we simply publish it as a pre-signed zip file. It should be added as a binary to the GitHub release.
+
+4. The release should have updated the versions of a few `package.json` files. Add and commit them, then add a git tag in the format of `v6.x.x`. Push both the commit and the tag to GitHub, and publish the release on GitHub (we should probably automate this with local script + GitHub actions).
diff --git a/vue-devtools/packages/docs/tailwind.config.cjs b/vue-devtools/packages/docs/tailwind.config.cjs
new file mode 100644
index 0000000000000000000000000000000000000000..34366c5314eead253bded26ac3567161cfa95dc6
--- /dev/null
+++ b/vue-devtools/packages/docs/tailwind.config.cjs
@@ -0,0 +1,12 @@
+const path = require('node:path')
+const base = require('../../tailwind.config.js')
+
+base.purge.content.push(
+ path.resolve(__dirname, './src/**/*.{js,jsx,ts,tsx,vue}'),
+)
+
+base.corePlugins = {
+ preflight: false,
+}
+
+module.exports = base
diff --git a/vue-devtools/packages/shared-utils/package.json b/vue-devtools/packages/shared-utils/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..f037d5d9573c186ed5cbb745bbe57b55e9d42e1a
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "@vue-devtools/shared-utils",
+ "version": "0.0.0",
+ "private": true,
+ "sideEffects": false,
+ "main": "./lib/index.js",
+ "types": "./lib/index.d.ts",
+ "scripts": {
+ "build": "rimraf lib && yarn ts",
+ "build:watch": "yarn ts -w",
+ "ts": "tsc -p tsconfig.json -d -outDir lib"
+ },
+ "dependencies": {
+ "@vue/devtools-api": "^6.0.0-beta.11"
+ },
+ "devDependencies": {
+ "@types/node": "^20.11.16",
+ "@types/webpack-env": "^1.15.1",
+ "typescript": "^5.3.3"
+ }
+}
diff --git a/vue-devtools/packages/shared-utils/src/backend.ts b/vue-devtools/packages/shared-utils/src/backend.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e459789bdf75e2a09ee3d9b77a73e448111529d8
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/backend.ts
@@ -0,0 +1,80 @@
+export const backendInjections = {
+ instanceMap: new Map(),
+ isVueInstance: (() => false) as ((value: any) => boolean),
+ getCustomInstanceDetails: (() => ({})) as ((instance: any) => any),
+ getCustomObjectDetails: (() => undefined) as (value: any, proto: string) => any,
+}
+
+export function getInstanceMap() {
+ return backendInjections.instanceMap
+}
+
+export function getCustomInstanceDetails(instance) {
+ return backendInjections.getCustomInstanceDetails(instance)
+}
+
+export function getCustomObjectDetails(value, proto: string) {
+ return backendInjections.getCustomObjectDetails(value, proto)
+}
+
+export function isVueInstance(value) {
+ return backendInjections.isVueInstance(value)
+}
+
+// @TODO refactor
+export function getCustomRouterDetails(router) {
+ return {
+ _custom: {
+ type: 'router',
+ display: 'VueRouter',
+ value: {
+ options: router.options,
+ currentRoute: router.currentRoute,
+ },
+ fields: {
+ abstract: true,
+ },
+ },
+ }
+}
+
+// @TODO refactor
+export function getCustomStoreDetails(store) {
+ return {
+ _custom: {
+ type: 'store',
+ display: 'Store',
+ value: {
+ state: store.state,
+ getters: getCatchedGetters(store),
+ },
+ fields: {
+ abstract: true,
+ },
+ },
+ }
+}
+
+// @TODO refactor
+export function getCatchedGetters(store) {
+ const getters = {}
+
+ const origGetters = store.getters || {}
+ const keys = Object.keys(origGetters)
+ for (let i = 0; i < keys.length; i++) {
+ const key = keys[i]
+ Object.defineProperty(getters, key, {
+ enumerable: true,
+ get: () => {
+ try {
+ return origGetters[key]
+ }
+ catch (e) {
+ return e
+ }
+ },
+ })
+ }
+
+ return getters
+}
diff --git a/vue-devtools/packages/shared-utils/src/bridge.ts b/vue-devtools/packages/shared-utils/src/bridge.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6c6fab2b86dc492a76745f9f8fd5c5c3a829d29a
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/bridge.ts
@@ -0,0 +1,114 @@
+// eslint-disable-next-line unicorn/prefer-node-protocol
+import { EventEmitter } from 'events'
+import { raf } from './raf'
+
+const BATCH_DURATION = 100
+
+export class Bridge extends EventEmitter {
+ wall: any // @TODO
+ _batchingQueue: any[] // @TODO
+ _sendingQueue: any[][] // @TODO
+ _receivingQueue: any[] // @TODO
+ _sending: boolean
+ _timer: NodeJS.Timeout
+
+ constructor(wall) {
+ super()
+ this.setMaxListeners(Number.POSITIVE_INFINITY)
+ this.wall = wall
+ wall.listen((messages) => {
+ if (Array.isArray(messages)) {
+ messages.forEach(message => this._emit(message))
+ }
+ else {
+ this._emit(messages)
+ }
+ })
+ this._batchingQueue = []
+ this._sendingQueue = []
+ this._receivingQueue = []
+ this._sending = false
+ }
+
+ on(event: string | symbol, listener: (...args: any[]) => void): this {
+ const wrappedListener = async (...args) => {
+ try {
+ await listener(...args)
+ }
+ catch (e) {
+ console.error(`[Bridge] Error in listener for event ${event.toString()} with args:`, args)
+ console.error(e)
+ }
+ }
+ return super.on(event, wrappedListener)
+ }
+
+ send(event: string, payload?: any) {
+ this._batchingQueue.push({
+ event,
+ payload,
+ })
+
+ if (this._timer == null) {
+ this._timer = setTimeout(() => this._flush(), BATCH_DURATION)
+ }
+ }
+
+ /**
+ * Log a message to the devtools background page.
+ */
+
+ log(message: string) {
+ this.send('log', message)
+ }
+
+ _flush() {
+ if (this._batchingQueue.length) {
+ this._send(this._batchingQueue)
+ }
+ clearTimeout(this._timer)
+ this._timer = null
+ this._batchingQueue = []
+ }
+
+ // @TODO types
+ _emit(message) {
+ if (typeof message === 'string') {
+ this.emit(message)
+ }
+ else if (message._chunk) {
+ this._receivingQueue.push(message._chunk)
+ if (message.last) {
+ this.emit(message.event, this._receivingQueue)
+ this._receivingQueue = []
+ }
+ }
+ else if (message.event) {
+ this.emit(message.event, message.payload)
+ }
+ }
+
+ // @TODO types
+ _send(messages) {
+ this._sendingQueue.push(messages)
+ this._nextSend()
+ }
+
+ _nextSend() {
+ if (!this._sendingQueue.length || this._sending) {
+ return
+ }
+ this._sending = true
+ const messages = this._sendingQueue.shift()
+ try {
+ this.wall.send(messages)
+ }
+ catch (err) {
+ if (err.message === 'Message length exceeded maximum allowed length.') {
+ this._sendingQueue.splice(0, 0, messages.map(message => [message]))
+ }
+ }
+ this._sending = false
+ raf(() => this._nextSend())
+ }
+}
diff --git a/vue-devtools/packages/shared-utils/src/consts.ts b/vue-devtools/packages/shared-utils/src/consts.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3bddabb1adedf51d1bc6d8bfba5c3cef77760dcc
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/consts.ts
@@ -0,0 +1,136 @@
+export enum BuiltinTabs {
+ COMPONENTS = 'components',
+ TIMELINE = 'timeline',
+ PLUGINS = 'plugins',
+ SETTINGS = 'settings',
+}
+
+export enum BridgeEvents {
+ // Misc
+ TO_BACK_SUBSCRIBE = 'b:subscribe',
+ TO_BACK_UNSUBSCRIBE = 'b:unsubscribe',
+ /** Backend is ready */
+ TO_FRONT_READY = 'f:ready',
+ /** Displays the "detected Vue" console log */
+ TO_BACK_LOG_DETECTED_VUE = 'b:log-detected-vue',
+ /** Force refresh */
+ TO_BACK_REFRESH = 'b:refresh',
+ /** Tab was switched */
+ TO_BACK_TAB_SWITCH = 'b:tab:switch',
+ TO_BACK_LOG = 'b:log',
+ /** Reconnected after background script is terminated (idle) */
+ TO_FRONT_RECONNECTED = 'f:reconnected',
+ /** Change app title (electron) */
+ TO_FRONT_TITLE = 'f:title',
+
+ // Apps
+ /** App was registered */
+ TO_FRONT_APP_ADD = 'f:app:add',
+ /** Get app list */
+ TO_BACK_APP_LIST = 'b:app:list',
+ TO_FRONT_APP_LIST = 'f:app:list',
+ TO_FRONT_APP_REMOVE = 'f:app:remove',
+ TO_BACK_APP_SELECT = 'b:app:select',
+ TO_FRONT_APP_SELECTED = 'f:app:selected',
+ TO_BACK_SCAN_LEGACY_APPS = 'b:app:scan-legacy',
+
+ // Components
+ TO_BACK_COMPONENT_TREE = 'b:component:tree',
+ TO_FRONT_COMPONENT_TREE = 'f:component:tree',
+ TO_BACK_COMPONENT_SELECTED_DATA = 'b:component:selected-data',
+ TO_FRONT_COMPONENT_SELECTED_DATA = 'f:component:selected-data',
+ TO_BACK_COMPONENT_EXPAND = 'b:component:expand',
+ TO_FRONT_COMPONENT_EXPAND = 'f:component:expand',
+ TO_BACK_COMPONENT_SCROLL_TO = 'b:component:scroll-to',
+ TO_BACK_COMPONENT_FILTER = 'b:component:filter',
+ TO_BACK_COMPONENT_MOUSE_OVER = 'b:component:mouse-over',
+ TO_BACK_COMPONENT_MOUSE_OUT = 'b:component:mouse-out',
+ TO_BACK_COMPONENT_CONTEXT_MENU_TARGET = 'b:component:context-menu-target',
+ TO_BACK_COMPONENT_EDIT_STATE = 'b:component:edit-state',
+ TO_BACK_COMPONENT_PICK = 'b:component:pick',
+ TO_FRONT_COMPONENT_PICK = 'f:component:pick',
+ TO_BACK_COMPONENT_PICK_CANCELED = 'b:component:pick-canceled',
+ TO_FRONT_COMPONENT_PICK_CANCELED = 'f:component:pick-canceled',
+ TO_BACK_COMPONENT_INSPECT_DOM = 'b:component:inspect-dom',
+ TO_FRONT_COMPONENT_INSPECT_DOM = 'f:component:inspect-dom',
+ TO_BACK_COMPONENT_RENDER_CODE = 'b:component:render-code',
+ TO_FRONT_COMPONENT_RENDER_CODE = 'f:component:render-code',
+ TO_FRONT_COMPONENT_UPDATED = 'f:component:updated',
+
+ // Timeline
+ TO_FRONT_TIMELINE_EVENT = 'f:timeline:event',
+ TO_BACK_TIMELINE_LAYER_LIST = 'b:timeline:layer-list',
+ TO_FRONT_TIMELINE_LAYER_LIST = 'f:timeline:layer-list',
+ TO_FRONT_TIMELINE_LAYER_ADD = 'f:timeline:layer-add',
+ TO_BACK_TIMELINE_SHOW_SCREENSHOT = 'b:timeline:show-screenshot',
+ TO_BACK_TIMELINE_CLEAR = 'b:timeline:clear',
+ TO_BACK_TIMELINE_EVENT_DATA = 'b:timeline:event-data',
+ TO_FRONT_TIMELINE_EVENT_DATA = 'f:timeline:event-data',
+ TO_BACK_TIMELINE_LAYER_LOAD_EVENTS = 'b:timeline:layer-load-events',
+ TO_FRONT_TIMELINE_LAYER_LOAD_EVENTS = 'f:timeline:layer-load-events',
+ TO_BACK_TIMELINE_LOAD_MARKERS = 'b:timeline:load-markers',
+ TO_FRONT_TIMELINE_LOAD_MARKERS = 'f:timeline:load-markers',
+ TO_FRONT_TIMELINE_MARKER = 'f:timeline:marker',
+
+ // Plugins
+ TO_BACK_DEVTOOLS_PLUGIN_LIST = 'b:devtools-plugin:list',
+ TO_FRONT_DEVTOOLS_PLUGIN_LIST = 'f:devtools-plugin:list',
+ TO_FRONT_DEVTOOLS_PLUGIN_ADD = 'f:devtools-plugin:add',
+ TO_BACK_DEVTOOLS_PLUGIN_SETTING_UPDATED = 'b:devtools-plugin:setting-updated',
+
+ // Custom inspectors
+ TO_BACK_CUSTOM_INSPECTOR_LIST = 'b:custom-inspector:list',
+ TO_FRONT_CUSTOM_INSPECTOR_LIST = 'f:custom-inspector:list',
+ TO_FRONT_CUSTOM_INSPECTOR_ADD = 'f:custom-inspector:add',
+ TO_BACK_CUSTOM_INSPECTOR_TREE = 'b:custom-inspector:tree',
+ TO_FRONT_CUSTOM_INSPECTOR_TREE = 'f:custom-inspector:tree',
+ TO_BACK_CUSTOM_INSPECTOR_STATE = 'b:custom-inspector:state',
+ TO_FRONT_CUSTOM_INSPECTOR_STATE = 'f:custom-inspector:state',
+ TO_BACK_CUSTOM_INSPECTOR_EDIT_STATE = 'b:custom-inspector:edit-state',
+ TO_BACK_CUSTOM_INSPECTOR_ACTION = 'b:custom-inspector:action',
+ TO_BACK_CUSTOM_INSPECTOR_NODE_ACTION = 'b:custom-inspector:node-action',
+ TO_FRONT_CUSTOM_INSPECTOR_SELECT_NODE = 'f:custom-inspector:select-node',
+
+ // Custom state
+ TO_BACK_CUSTOM_STATE_ACTION = 'b:custom-state:action',
+}
+
+export enum BridgeSubscriptions {
+ SELECTED_COMPONENT_DATA = 'component:selected-data',
+ COMPONENT_TREE = 'component:tree',
+}
+
+export enum HookEvents {
+ INIT = 'init',
+ APP_INIT = 'app:init',
+ APP_ADD = 'app:add',
+ APP_UNMOUNT = 'app:unmount',
+ COMPONENT_UPDATED = 'component:updated',
+ COMPONENT_ADDED = 'component:added',
+ COMPONENT_REMOVED = 'component:removed',
+ COMPONENT_EMIT = 'component:emit',
+ COMPONENT_HIGHLIGHT = 'component:highlight',
+ COMPONENT_UNHIGHLIGHT = 'component:unhighlight',
+ SETUP_DEVTOOLS_PLUGIN = 'devtools-plugin:setup',
+ TIMELINE_LAYER_ADDED = 'timeline:layer-added',
+ TIMELINE_EVENT_ADDED = 'timeline:event-added',
+ CUSTOM_INSPECTOR_ADD = 'custom-inspector:add',
+ CUSTOM_INSPECTOR_SEND_TREE = 'custom-inspector:send-tree',
+ CUSTOM_INSPECTOR_SEND_STATE = 'custom-inspector:send-state',
+ CUSTOM_INSPECTOR_SELECT_NODE = 'custom-inspector:select-node',
+ PERFORMANCE_START = 'perf:start',
+ PERFORMANCE_END = 'perf:end',
+ PLUGIN_SETTINGS_SET = 'plugin:settings:set',
+ /**
+ * @deprecated
+ */
+ FLUSH = 'flush',
+ /**
+ * @deprecated
+ */
+ TRACK_UPDATE = '_track-update',
+ /**
+ * @deprecated
+ */
+ FLASH_UPDATE = '_flash-update',
+}
diff --git a/vue-devtools/packages/shared-utils/src/edit.ts b/vue-devtools/packages/shared-utils/src/edit.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b365c7f4ffe6ccdbe83bdb7260bad387b1a333f2
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/edit.ts
@@ -0,0 +1,89 @@
+import type { EditStatePayload } from '@vue/devtools-api'
+
+export class StateEditor {
+ set(object, path, value, cb = null) {
+ const sections = Array.isArray(path) ? path : path.split('.')
+ while (sections.length > 1) {
+ object = object[sections.shift()]
+ if (this.isRef(object)) {
+ object = this.getRefValue(object)
+ }
+ }
+ const field = sections[0]
+ if (cb) {
+ cb(object, field, value)
+ }
+ else if (this.isRef(object[field])) {
+ this.setRefValue(object[field], value)
+ }
+ else {
+ object[field] = value
+ }
+ }
+
+ get(object, path) {
+ const sections = Array.isArray(path) ? path : path.split('.')
+ for (let i = 0; i < sections.length; i++) {
+ object = object[sections[i]]
+ if (this.isRef(object)) {
+ object = this.getRefValue(object)
+ }
+ if (!object) {
+ return undefined
+ }
+ }
+ return object
+ }
+
+ has(object, path, parent = false) {
+ if (typeof object === 'undefined') {
+ return false
+ }
+
+ const sections = Array.isArray(path) ? path.slice() : path.split('.')
+ const size = !parent ? 1 : 2
+ while (object && sections.length > size) {
+ object = object[sections.shift()]
+ if (this.isRef(object)) {
+ object = this.getRefValue(object)
+ }
+ }
+ return object != null && Object.prototype.hasOwnProperty.call(object, sections[0])
+ }
+
+ createDefaultSetCallback(state: EditStatePayload) {
+ return (obj, field, value) => {
+ if (state.remove || state.newKey) {
+ if (Array.isArray(obj)) {
+ obj.splice(field, 1)
+ }
+ else {
+ delete obj[field]
+ }
+ }
+ if (!state.remove) {
+ const target = obj[state.newKey || field]
+ if (this.isRef(target)) {
+ this.setRefValue(target, value)
+ }
+ else {
+ obj[state.newKey || field] = value
+ }
+ }
+ }
+ }
+
+ isRef(_ref: any): boolean {
+ // To implement in subclass
+ return false
+ }
+
+ setRefValue(_ref: any, _value: any): void {
+ // To implement in subclass
+ }
+
+ getRefValue(ref: any): any {
+ // To implement in subclass
+ return ref
+ }
+}
diff --git a/vue-devtools/packages/shared-utils/src/env.ts b/vue-devtools/packages/shared-utils/src/env.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bba23763386b912c51fe37d0197148979a7a6145
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/env.ts
@@ -0,0 +1,46 @@
+import type { App } from 'vue'
+
+export const isBrowser = typeof navigator !== 'undefined'
+export const target: any = isBrowser
+ ? window
+ : typeof globalThis !== 'undefined'
+ ? globalThis
+ : {}
+export const isChrome = typeof target.chrome !== 'undefined' && !!target.chrome.devtools
+export const isFirefox = isBrowser && navigator.userAgent.includes('Firefox')
+export const isWindows = isBrowser && navigator.platform.indexOf('Win') === 0
+export const isMac = isBrowser && navigator.platform === 'MacIntel'
+export const isLinux = isBrowser && navigator.platform.indexOf('Linux') === 0
+export const keys = {
+ ctrl: isMac ? '⌘' : 'Ctrl',
+ shift: 'Shift',
+ alt: isMac ? '⌥' : 'Alt',
+ del: 'Del',
+ enter: 'Enter',
+ esc: 'Esc',
+}
+
+export function initEnv(app: App) {
+ if (Object.prototype.hasOwnProperty.call(app.config.globalProperties, '$isChrome')) {
+ return
+ }
+
+ Object.defineProperties(app.config.globalProperties, {
+ $isChrome: { get: () => isChrome },
+ $isFirefox: { get: () => isFirefox },
+ $isWindows: { get: () => isWindows },
+ $isMac: { get: () => isMac },
+ $isLinux: { get: () => isLinux },
+ $keys: { get: () => keys },
+ })
+
+ if (isWindows) {
+ document.body.classList.add('platform-windows')
+ }
+ if (isMac) {
+ document.body.classList.add('platform-mac')
+ }
+ if (isLinux) {
+ document.body.classList.add('platform-linux')
+ }
+}
diff --git a/vue-devtools/packages/shared-utils/src/index.ts b/vue-devtools/packages/shared-utils/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fc485f5fb346c6f1ee62b4f42ec06d191f71f1a9
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/index.ts
@@ -0,0 +1,14 @@
+export * from './backend'
+export * from './bridge'
+export * from './consts'
+export * from './edit'
+export * from './env'
+export * from './plugin-permissions'
+export * from './plugin-settings'
+export * from './shared-data'
+export * from './shell'
+export * from './storage'
+export * from './throttle'
+export * from './transfer'
+export * from './util'
+export * from './raf'
diff --git a/vue-devtools/packages/shared-utils/src/plugin-permissions.ts b/vue-devtools/packages/shared-utils/src/plugin-permissions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..19ef867771334ca9182e978a7368c4abe6ce8097
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/plugin-permissions.ts
@@ -0,0 +1,23 @@
+import { SharedData } from './shared-data'
+
+export enum PluginPermission {
+ ENABLED = 'enabled',
+ COMPONENTS = 'components',
+ CUSTOM_INSPECTOR = 'custom-inspector',
+ TIMELINE = 'timeline',
+}
+
+export function hasPluginPermission(pluginId: string, permission: PluginPermission) {
+ const result = SharedData.pluginPermissions[`${pluginId}:${permission}`]
+ if (result == null) {
+ return true
+ }
+ return !!result
+}
+
+export function setPluginPermission(pluginId: string, permission: PluginPermission, active: boolean) {
+ SharedData.pluginPermissions = {
+ ...SharedData.pluginPermissions,
+ [`${pluginId}:${permission}`]: active,
+ }
+}
diff --git a/vue-devtools/packages/shared-utils/src/plugin-settings.ts b/vue-devtools/packages/shared-utils/src/plugin-settings.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d351fd129ae689441dc330e458d0a2b09659e536
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/plugin-settings.ts
@@ -0,0 +1,27 @@
+import type { PluginSettingsItem } from '@vue/devtools-api'
+import { SharedData } from './shared-data'
+
+export function getPluginSettings = any>(pluginId: string, defaultSettings?: TSettings): TSettings {
+ return {
+ ...defaultSettings ?? {},
+ ...SharedData.pluginSettings[pluginId] ?? {},
+ }
+}
+
+export function setPluginSettings = any>(pluginId: string, settings: TSettings) {
+ SharedData.pluginSettings = {
+ ...SharedData.pluginSettings,
+ [pluginId]: settings,
+ }
+}
+
+export function getPluginDefaultSettings = any>(schema: Record): TSettings {
+ const result: Record = {}
+ if (schema) {
+ for (const id in schema) {
+ const item = schema[id]
+ result[id] = item.defaultValue
+ }
+ }
+ return result as TSettings
+}
diff --git a/vue-devtools/packages/shared-utils/src/raf.ts b/vue-devtools/packages/shared-utils/src/raf.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fe16a210603a8e1fa0223b4fe8f394ad78ee04e8
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/raf.ts
@@ -0,0 +1,20 @@
+let pendingCallbacks: Array<(time: number) => void> = []
+
+/**
+ * requestAnimationFrame that also works on non-browser environments like Node.
+ */
+export const raf = typeof requestAnimationFrame === 'function'
+ ? requestAnimationFrame
+ : (fn: (time: number) => void) => {
+ if (!pendingCallbacks.length) {
+ setImmediate(() => {
+ const now = performance.now()
+ const cbs = pendingCallbacks
+ // in case cbs add new callbacks
+ pendingCallbacks = []
+ cbs.forEach(cb => cb(now))
+ })
+ }
+
+ pendingCallbacks.push(fn)
+ }
diff --git a/vue-devtools/packages/shared-utils/src/shared-data.ts b/vue-devtools/packages/shared-utils/src/shared-data.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4987dbf44b6f0315ce7262fb2f811018c750b92f
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/shared-data.ts
@@ -0,0 +1,240 @@
+import { reactive } from 'vue'
+import { getStorage, setStorage } from './storage'
+import type { Bridge } from './bridge'
+import { isBrowser, isMac } from './env'
+
+// Initial state
+const internalSharedData = {
+ openInEditorHost: '/',
+ componentNameStyle: 'class',
+ theme: 'auto',
+ displayDensity: 'low',
+ timeFormat: 'default',
+ recordVuex: true,
+ cacheVuexSnapshotsEvery: 50,
+ cacheVuexSnapshotsLimit: 10,
+ snapshotLoading: false,
+ componentEventsEnabled: true,
+ performanceMonitoringEnabled: true,
+ editableProps: false,
+ logDetected: true,
+ vuexNewBackend: false,
+ vuexAutoload: false,
+ vuexGroupGettersByModule: true,
+ showMenuScrollTip: true,
+ timelineRecording: false,
+ timelineTimeGrid: true,
+ timelineScreenshots: false,
+ menuStepScrolling: isMac,
+ pluginPermissions: {} as any,
+ pluginSettings: {} as any,
+ pageConfig: {} as any,
+ legacyApps: false,
+ trackUpdates: true,
+ flashUpdates: false,
+ debugInfo: false,
+ isBrowser,
+}
+
+type TSharedData = typeof internalSharedData
+
+const persisted = [
+ 'componentNameStyle',
+ 'theme',
+ 'displayDensity',
+ 'recordVuex',
+ 'editableProps',
+ 'logDetected',
+ 'vuexNewBackend',
+ 'vuexAutoload',
+ 'vuexGroupGettersByModule',
+ 'timeFormat',
+ 'showMenuScrollTip',
+ 'timelineRecording',
+ 'timelineTimeGrid',
+ 'timelineScreenshots',
+ 'menuStepScrolling',
+ 'pluginPermissions',
+ 'pluginSettings',
+ 'performanceMonitoringEnabled',
+ 'componentEventsEnabled',
+ 'trackUpdates',
+ 'flashUpdates',
+ 'debugInfo',
+]
+
+const storageVersion = '6.0.0-alpha.1'
+
+// ---- INTERNALS ---- //
+
+let bridge
+// List of fields to persist to storage (disabled if 'false')
+// This should be unique to each shared data client to prevent conflicts
+let persist = false
+let data
+
+let initRetryInterval
+let initRetryCount = 0
+
+export interface SharedDataParams {
+ bridge: Bridge
+ persist: boolean
+}
+
+const initCbs = []
+
+export function initSharedData(params: SharedDataParams): Promise {
+ return new Promise((resolve) => {
+ // Mandatory params
+ bridge = params.bridge
+ persist = !!params.persist
+
+ if (persist) {
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log('[shared data] Master init in progress...')
+ }
+ // Load persisted fields
+ persisted.forEach((key) => {
+ const value = getStorage(`vue-devtools-${storageVersion}:shared-data:${key}`)
+ if (value !== null) {
+ internalSharedData[key] = value
+ }
+ })
+ bridge.on('shared-data:load', () => {
+ // Send all fields
+ Object.keys(internalSharedData).forEach((key) => {
+ sendValue(key, internalSharedData[key])
+ })
+ bridge.send('shared-data:load-complete')
+ })
+ bridge.on('shared-data:init-complete', () => {
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log('[shared data] Master init complete')
+ }
+ clearInterval(initRetryInterval)
+ resolve()
+ })
+
+ bridge.send('shared-data:master-init-waiting')
+ // In case backend init is executed after frontend
+ bridge.on('shared-data:minion-init-waiting', () => {
+ bridge.send('shared-data:master-init-waiting')
+ })
+
+ initRetryCount = 0
+ clearInterval(initRetryInterval)
+ initRetryInterval = setInterval(() => {
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log('[shared data] Master init retrying...')
+ }
+ bridge.send('shared-data:master-init-waiting')
+ initRetryCount++
+ if (initRetryCount > 30) {
+ clearInterval(initRetryInterval)
+ console.error('[shared data] Master init failed')
+ }
+ }, 2000)
+ }
+ else {
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log('[shared data] Minion init in progress...')
+ }
+ bridge.on('shared-data:master-init-waiting', () => {
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log('[shared data] Minion loading data...')
+ }
+ // Load all persisted shared data
+ bridge.send('shared-data:load')
+ bridge.once('shared-data:load-complete', () => {
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log('[shared data] Minion init complete')
+ }
+ bridge.send('shared-data:init-complete')
+ resolve()
+ })
+ })
+ bridge.send('shared-data:minion-init-waiting')
+ }
+
+ data = reactive({ ...internalSharedData })
+
+ // Update value from other shared data clients
+ bridge.on('shared-data:set', ({ key, value }) => {
+ setValue(key, value)
+ })
+
+ initCbs.forEach(cb => cb())
+ })
+}
+
+export function onSharedDataInit(cb) {
+ initCbs.push(cb)
+ return () => {
+ const index = initCbs.indexOf(cb)
+ if (index !== -1) {
+ initCbs.splice(index, 1)
+ }
+ }
+}
+
+let watchers: Partial unknown)[]>> = {}
+
+export function destroySharedData() {
+ bridge.removeAllListeners('shared-data:set')
+ watchers = {}
+}
+
+function setValue(key: string, value: any) {
+ // Storage
+ if (persist && persisted.includes(key)) {
+ setStorage(`vue-devtools-${storageVersion}:shared-data:${key}`, value)
+ }
+ const oldValue = data[key]
+ data[key] = value
+ const handlers = watchers[key]
+ if (handlers) {
+ handlers.forEach(h => h(value, oldValue))
+ }
+ // Validate Proxy set trap
+ return true
+}
+
+function sendValue(key: string, value: any) {
+ bridge && bridge.send('shared-data:set', {
+ key,
+ value,
+ })
+}
+
+export function watchSharedData<
+ TKey extends keyof TSharedData,
+>(prop: TKey, handler: (value: TSharedData[TKey], oldValue: TSharedData[TKey]) => unknown) {
+ const list = watchers[prop] || (watchers[prop] = [])
+ list.push(handler)
+ return () => {
+ const index = list.indexOf(handler)
+ if (index !== -1) {
+ list.splice(index, 1)
+ }
+ }
+}
+
+const proxy: Partial = {}
+Object.keys(internalSharedData).forEach((key) => {
+ Object.defineProperty(proxy, key, {
+ configurable: false,
+ get: () => data[key],
+ set: (value) => {
+ sendValue(key, value)
+ setValue(key, value)
+ },
+ })
+})
+
+export const SharedData = proxy
diff --git a/vue-devtools/packages/shared-utils/src/shell.ts b/vue-devtools/packages/shared-utils/src/shell.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1bdc75b92eb0f2b489a9d5c2d2dff9d0509965d6
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/shell.ts
@@ -0,0 +1,6 @@
+import type { Bridge } from './bridge'
+
+export interface Shell {
+ connect: (cb: ((bridge: Bridge) => void | Promise)) => void
+ onReload: (cb: (() => void | Promise)) => void
+}
diff --git a/vue-devtools/packages/shared-utils/src/storage.ts b/vue-devtools/packages/shared-utils/src/storage.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5cd4e2c203dce1d0b2eaab7d284c4087e432be37
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/storage.ts
@@ -0,0 +1,91 @@
+import { target } from './env'
+
+// If we can, we use the browser extension API to store data
+// it's async though, so we synchronize changes from an intermediate
+// storageData object
+const useStorage = typeof target.chrome !== 'undefined' && typeof target.chrome.storage !== 'undefined'
+
+let storageData = null
+
+export function initStorage(): Promise {
+ return new Promise((resolve) => {
+ if (useStorage) {
+ target.chrome.storage.local.get(null, (result) => {
+ storageData = result
+ resolve()
+ })
+ }
+ else {
+ storageData = {}
+ resolve()
+ }
+ })
+}
+
+export function getStorage(key: string, defaultValue: any = null) {
+ checkStorage()
+ if (useStorage) {
+ return getDefaultValue(storageData[key], defaultValue)
+ }
+ else {
+ try {
+ return getDefaultValue(JSON.parse(localStorage.getItem(key)), defaultValue)
+ }
+ catch (e) {}
+ }
+}
+
+export function setStorage(key: string, val: any) {
+ checkStorage()
+ if (useStorage) {
+ storageData[key] = val
+ target.chrome.storage.local.set({ [key]: val })
+ }
+ else {
+ try {
+ localStorage.setItem(key, JSON.stringify(val))
+ }
+ catch (e) {}
+ }
+}
+
+export function removeStorage(key: string) {
+ checkStorage()
+ if (useStorage) {
+ delete storageData[key]
+ target.chrome.storage.local.remove([key])
+ }
+ else {
+ try {
+ localStorage.removeItem(key)
+ }
+ catch (e) {}
+ }
+}
+
+export function clearStorage() {
+ checkStorage()
+ if (useStorage) {
+ storageData = {}
+ target.chrome.storage.local.clear()
+ }
+ else {
+ try {
+ localStorage.clear()
+ }
+ catch (e) {}
+ }
+}
+
+function checkStorage() {
+ if (!storageData) {
+ throw new Error('Storage wasn\'t initialized with \'init()\'')
+ }
+}
+
+function getDefaultValue(value, defaultValue) {
+ if (value == null) {
+ return defaultValue
+ }
+ return value
+}
diff --git a/vue-devtools/packages/shared-utils/src/throttle.ts b/vue-devtools/packages/shared-utils/src/throttle.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ccf981ed33645ac90d3b81c5131543fc5aa16646
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/throttle.ts
@@ -0,0 +1,38 @@
+import throttle from 'lodash/throttle'
+
+interface ThrottleQueueItem {
+ fn: Function
+ key: string
+}
+
+export function createThrottleQueue(wait: number) {
+ const queue: ThrottleQueueItem[] = []
+ const tracker: Map = new Map()
+
+ function flush() {
+ for (const item of queue) {
+ item.fn()
+ tracker.delete(item.key)
+ }
+ queue.length = 0
+ }
+
+ const throttledFlush = throttle(flush, wait)
+
+ function add(key: string, fn: Function) {
+ if (!tracker.has(key)) {
+ const item = { key, fn }
+ queue.push(item)
+ tracker.set(key, item)
+ throttledFlush()
+ }
+ else {
+ const item = tracker.get(key)!
+ item.fn = fn
+ }
+ }
+
+ return {
+ add,
+ }
+}
diff --git a/vue-devtools/packages/shared-utils/src/transfer.ts b/vue-devtools/packages/shared-utils/src/transfer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2a576ee5a50b2f81c1c3034f54f62669eccd5978
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/transfer.ts
@@ -0,0 +1,126 @@
+const MAX_SERIALIZED_SIZE = 512 * 1024 // 1MB
+
+function encode(data, replacer, list, seen) {
+ let stored, key, value, i, l
+ const seenIndex = seen.get(data)
+ if (seenIndex != null) {
+ return seenIndex
+ }
+ const index = list.length
+ const proto = Object.prototype.toString.call(data)
+ if (proto === '[object Object]') {
+ stored = {}
+ seen.set(data, index)
+ list.push(stored)
+ const keys = Object.keys(data)
+ for (i = 0, l = keys.length; i < l; i++) {
+ key = keys[i]
+ try {
+ value = data[key]
+ if (replacer) {
+ value = replacer.call(data, key, value)
+ }
+ }
+ catch (e) {
+ value = e
+ }
+ stored[key] = encode(value, replacer, list, seen)
+ }
+ }
+ else if (proto === '[object Array]') {
+ stored = []
+ seen.set(data, index)
+ list.push(stored)
+ for (i = 0, l = data.length; i < l; i++) {
+ try {
+ value = data[i]
+ if (replacer) {
+ value = replacer.call(data, i, value)
+ }
+ }
+ catch (e) {
+ value = e
+ }
+ stored[i] = encode(value, replacer, list, seen)
+ }
+ }
+ else {
+ list.push(data)
+ }
+ return index
+}
+
+function decode(list, reviver) {
+ let i = list.length
+ let j, k, data, key, value, proto
+ while (i--) {
+ data = list[i]
+ proto = Object.prototype.toString.call(data)
+ if (proto === '[object Object]') {
+ const keys = Object.keys(data)
+ for (j = 0, k = keys.length; j < k; j++) {
+ key = keys[j]
+ value = list[data[key]]
+ if (reviver) {
+ value = reviver.call(data, key, value)
+ }
+ data[key] = value
+ }
+ }
+ else if (proto === '[object Array]') {
+ for (j = 0, k = data.length; j < k; j++) {
+ value = list[data[j]]
+ if (reviver) {
+ value = reviver.call(data, j, value)
+ }
+ data[j] = value
+ }
+ }
+ }
+}
+
+export function stringifyCircularAutoChunks(data: any, replacer: (this: any, key: string, value: any) => any = null, space: number = null) {
+ let result
+ try {
+ result = arguments.length === 1
+ ? JSON.stringify(data)
+ : JSON.stringify(data, replacer, space)
+ }
+ catch (e) {
+ result = stringifyStrictCircularAutoChunks(data, replacer, space)
+ }
+ if (result.length > MAX_SERIALIZED_SIZE) {
+ const chunkCount = Math.ceil(result.length / MAX_SERIALIZED_SIZE)
+ const chunks = []
+ for (let i = 0; i < chunkCount; i++) {
+ chunks.push(result.slice(i * MAX_SERIALIZED_SIZE, (i + 1) * MAX_SERIALIZED_SIZE))
+ }
+ return chunks
+ }
+ return result
+}
+
+export function parseCircularAutoChunks(data: any, reviver: (this: any, key: string, value: any) => any = null) {
+ if (Array.isArray(data)) {
+ data = data.join('')
+ }
+ const hasCircular = /^\s/.test(data)
+ if (!hasCircular) {
+ return arguments.length === 1
+ ? JSON.parse(data)
+ : JSON.parse(data, reviver)
+ }
+ else {
+ const list = JSON.parse(data)
+ decode(list, reviver)
+ return list[0]
+ }
+}
+
+export function stringifyStrictCircularAutoChunks(data: any, replacer: (this: any, key: string, value: any) => any = null, space: number = null) {
+ const list = []
+ encode(data, replacer, list, new Map())
+ return space
+ ? ` ${JSON.stringify(list, null, space)}`
+ : ` ${JSON.stringify(list)}`
+}
diff --git a/vue-devtools/packages/shared-utils/src/util.ts b/vue-devtools/packages/shared-utils/src/util.ts
new file mode 100644
index 0000000000000000000000000000000000000000..61fc5f8422b903399c10c9de41eb6c975f2adb9b
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/src/util.ts
@@ -0,0 +1,877 @@
+// eslint-disable-next-line unicorn/prefer-node-protocol
+import path from 'path'
+import type { CustomState } from '@vue/devtools-api'
+import { parseCircularAutoChunks, stringifyCircularAutoChunks } from './transfer'
+import {
+ getCustomInstanceDetails,
+ getCustomObjectDetails,
+ getCustomRouterDetails,
+ getCustomStoreDetails,
+ getInstanceMap,
+ isVueInstance,
+} from './backend'
+import { SharedData } from './shared-data'
+import { isChrome, target } from './env'
+
+function cached(fn) {
+ const cache = Object.create(null)
+ return function cachedFn(str) {
+ const hit = cache[str]
+ return hit || (cache[str] = fn(str))
+ }
+}
+
+const classifyRE = /(?:^|[-_/])(\w)/g
+export const classify = cached((str) => {
+ // fix: str.replace may causes '"replace" is not a function' exception.
+ // This bug may causes the UI 'Component Filter' to not work properly
+ // e.g. The type of 'str' is Number.
+ // So need cover 'str' to String.
+ return str && (`${str}`).replace(classifyRE, toUpper)
+})
+
+const camelizeRE = /-(\w)/g
+export const camelize = cached((str) => {
+ return str && str.replace(camelizeRE, toUpper)
+})
+
+const kebabizeRE = /([a-z0-9])([A-Z])/g
+export const kebabize = cached((str) => {
+ return str && str
+ .replace(kebabizeRE, (_, lowerCaseCharacter, upperCaseLetter) => {
+ return `${lowerCaseCharacter}-${upperCaseLetter}`
+ })
+ .toLowerCase()
+})
+
+function toUpper(_, c) {
+ return c ? c.toUpperCase() : ''
+}
+
+export function getComponentDisplayName(originalName, style = 'class') {
+ switch (style) {
+ case 'class':
+ return classify(originalName)
+ case 'kebab':
+ return kebabize(originalName)
+ case 'original':
+ default:
+ return originalName
+ }
+}
+
+export function inDoc(node) {
+ if (!node) {
+ return false
+ }
+ const doc = node.ownerDocument.documentElement
+ const parent = node.parentNode
+ return doc === node
+ || doc === parent
+ || !!(parent && parent.nodeType === 1 && (doc.contains(parent)))
+}
+
+/**
+ * Stringify/parse data using CircularJSON.
+ */
+
+export const UNDEFINED = '__vue_devtool_undefined__'
+export const INFINITY = '__vue_devtool_infinity__'
+export const NEGATIVE_INFINITY = '__vue_devtool_negative_infinity__'
+export const NAN = '__vue_devtool_nan__'
+
+export const SPECIAL_TOKENS = {
+ 'true': true,
+ 'false': false,
+ 'undefined': UNDEFINED,
+ 'null': null,
+ '-Infinity': NEGATIVE_INFINITY,
+ 'Infinity': INFINITY,
+ 'NaN': NAN,
+}
+
+export const MAX_STRING_SIZE = 10000
+export const MAX_ARRAY_SIZE = 5000
+
+export function specialTokenToString(value) {
+ if (value === null) {
+ return 'null'
+ }
+ else if (value === UNDEFINED) {
+ return 'undefined'
+ }
+ else if (value === NAN) {
+ return 'NaN'
+ }
+ else if (value === INFINITY) {
+ return 'Infinity'
+ }
+ else if (value === NEGATIVE_INFINITY) {
+ return '-Infinity'
+ }
+ return false
+}
+
+/**
+ * Needed to prevent stack overflow
+ * while replacing complex objects
+ * like components because we create
+ * new objects with the CustomValue API
+ * (.i.e `{ _custom: { ... } }`)
+ */
+class EncodeCache {
+ map: Map
+
+ constructor() {
+ this.map = new Map()
+ }
+
+ /**
+ * Returns a result unique to each input data
+ * @param {*} data Input data
+ * @param {*} factory Function used to create the unique result
+ */
+ cache(data: TData, factory: (data: TData) => TResult): TResult {
+ const cached: TResult = this.map.get(data)
+ if (cached) {
+ return cached
+ }
+ else {
+ const result = factory(data)
+ this.map.set(data, result)
+ return result
+ }
+ }
+
+ clear() {
+ this.map.clear()
+ }
+}
+
+const encodeCache = new EncodeCache()
+
+class ReviveCache {
+ map: Map
+ index: number
+ size: number
+ maxSize: number
+
+ constructor(maxSize: number) {
+ this.maxSize = maxSize
+ this.map = new Map()
+ this.index = 0
+ this.size = 0
+ }
+
+ cache(value: any) {
+ const currentIndex = this.index
+ this.map.set(currentIndex, value)
+ this.size++
+ if (this.size > this.maxSize) {
+ this.map.delete(currentIndex - this.size)
+ this.size--
+ }
+ this.index++
+ return currentIndex
+ }
+
+ read(id: number) {
+ return this.map.get(id)
+ }
+}
+
+const reviveCache = new ReviveCache(1000)
+
+const replacers = {
+ internal: replacerForInternal,
+ user: replaceForUser,
+}
+
+export function stringify(data, target: keyof typeof replacers = 'internal') {
+ // Create a fresh cache for each serialization
+ encodeCache.clear()
+ return stringifyCircularAutoChunks(data, replacers[target])
+}
+
+function replacerForInternal(key) {
+ // @ts-expect-error meow
+ const val = this[key]
+ const type = typeof val
+ if (Array.isArray(val)) {
+ const l = val.length
+ if (l > MAX_ARRAY_SIZE) {
+ return {
+ _isArray: true,
+ length: l,
+ items: val.slice(0, MAX_ARRAY_SIZE),
+ }
+ }
+ return val
+ }
+ else if (typeof val === 'string') {
+ if (val.length > MAX_STRING_SIZE) {
+ return `${val.substring(0, MAX_STRING_SIZE)}... (${(val.length)} total length)`
+ }
+ else {
+ return val
+ }
+ }
+ else if (type === 'undefined') {
+ return UNDEFINED
+ }
+ else if (val === Number.POSITIVE_INFINITY) {
+ return INFINITY
+ }
+ else if (val === Number.NEGATIVE_INFINITY) {
+ return NEGATIVE_INFINITY
+ }
+ else if (type === 'function') {
+ return getCustomFunctionDetails(val)
+ }
+ else if (type === 'symbol') {
+ return `[native Symbol ${Symbol.prototype.toString.call(val)}]`
+ }
+ else if (type === 'bigint') {
+ return getCustomBigIntDetails(val)
+ }
+ else if (val !== null && type === 'object') {
+ const proto = Object.prototype.toString.call(val)
+ if (proto === '[object Map]') {
+ return encodeCache.cache(val, () => getCustomMapDetails(val))
+ }
+ else if (proto === '[object Set]') {
+ return encodeCache.cache(val, () => getCustomSetDetails(val))
+ }
+ else if (proto === '[object RegExp]') {
+ // special handling of native type
+ return `[native RegExp ${RegExp.prototype.toString.call(val)}]`
+ }
+ else if (proto === '[object Date]') {
+ return getCustomDateDetails(val)
+ }
+ else if (proto === '[object Error]') {
+ return `[native Error ${val.message}<>${val.stack}]`
+ }
+ else if (val.state && val._vm) {
+ return encodeCache.cache(val, () => getCustomStoreDetails(val))
+ }
+ else if (val.constructor && val.constructor.name === 'VueRouter') {
+ return encodeCache.cache(val, () => getCustomRouterDetails(val))
+ }
+ else if (isVueInstance(val)) {
+ return encodeCache.cache(val, () => getCustomInstanceDetails(val))
+ }
+ else if (typeof val.render === 'function') {
+ return encodeCache.cache(val, () => getCustomComponentDefinitionDetails(val))
+ }
+ else if (val.constructor && val.constructor.name === 'VNode') {
+ return `[native VNode <${val.tag}>]`
+ }
+ else if (typeof HTMLElement !== 'undefined' && val instanceof HTMLElement) {
+ return encodeCache.cache(val, () => getCustomHTMLElementDetails(val))
+ }
+ else if (val.constructor?.name === 'Store' && val._wrappedGetters) {
+ return `[object Store]`
+ }
+ else if (val.currentRoute) {
+ return `[object Router]`
+ }
+ const customDetails = getCustomObjectDetails(val, proto)
+ if (customDetails != null) {
+ return customDetails
+ }
+ }
+ else if (Number.isNaN(val)) {
+ return NAN
+ }
+ return sanitize(val)
+}
+
+// @TODO revive from backend to have more data to the clipboard
+function replaceForUser(key) {
+ // @ts-expect-error meow
+ let val = this[key]
+ const type = typeof val
+ if (val?._custom && 'value' in val._custom) {
+ val = val._custom.value
+ }
+ if (type !== 'object') {
+ if (val === UNDEFINED) {
+ return undefined
+ }
+ else if (val === INFINITY) {
+ return Number.POSITIVE_INFINITY
+ }
+ else if (val === NEGATIVE_INFINITY) {
+ return Number.NEGATIVE_INFINITY
+ }
+ else if (val === NAN) {
+ return Number.NaN
+ }
+ return val
+ }
+ return sanitize(val)
+}
+
+export function getCustomMapDetails(val) {
+ const list = []
+ val.forEach(
+ (value, key) => list.push({
+ key,
+ value,
+ }),
+ )
+ return {
+ _custom: {
+ type: 'map',
+ display: 'Map',
+ value: list,
+ readOnly: true,
+ fields: {
+ abstract: true,
+ },
+ },
+ }
+}
+
+export function reviveMap(val) {
+ const result = new Map()
+ const list = val._custom.value
+ for (let i = 0; i < list.length; i++) {
+ const { key, value } = list[i]
+ result.set(key, revive(value))
+ }
+ return result
+}
+
+export function getCustomSetDetails(val) {
+ const list = Array.from(val)
+ return {
+ _custom: {
+ type: 'set',
+ display: `Set[${list.length}]`,
+ value: list,
+ readOnly: true,
+ },
+ }
+}
+
+export function reviveSet(val) {
+ const result = new Set()
+ const list = val._custom.value
+ for (let i = 0; i < list.length; i++) {
+ const value = list[i]
+ result.add(revive(value))
+ }
+ return result
+}
+
+export function getCustomBigIntDetails(val) {
+ const stringifiedBigInt = BigInt.prototype.toString.call(val)
+ return {
+ _custom: {
+ type: 'bigint',
+ display: `BigInt(${stringifiedBigInt})`,
+ value: stringifiedBigInt,
+ },
+ }
+}
+
+export function getCustomDateDetails(val: Date) {
+ const dateCopy = new Date(val.getTime())
+ dateCopy.setMinutes(dateCopy.getMinutes() - dateCopy.getTimezoneOffset())
+
+ const displayedTime = Date.prototype.toString.call(val)
+ return {
+ _custom: {
+ type: 'date',
+ display: displayedTime,
+ value: dateCopy.toISOString().slice(0, -1),
+ skipSerialize: true,
+ },
+ }
+}
+
+// Use a custom basename functions instead of the shimed version
+// because it doesn't work on Windows
+export function basename(filename, ext) {
+ filename = filename.replace(/\\/g, '/')
+ if (filename.includes(`/index${ext}`)) {
+ filename = filename.replace(`/index${ext}`, ext)
+ }
+ return path.basename(
+ filename.replace(/^[a-z]:/i, ''),
+ ext,
+ )
+}
+
+export function getComponentName(options) {
+ const name = options.displayName || options.name || options._componentTag
+ if (name) {
+ return name
+ }
+ const file = options.__file // injected by vue-loader
+ if (file) {
+ return classify(basename(file, '.vue'))
+ }
+}
+
+export function getCustomComponentDefinitionDetails(def) {
+ let display = getComponentName(def)
+ if (display) {
+ if (def.name && def.__file) {
+ display += ` (${def.__file})`
+ }
+ }
+ else {
+ display = 'Unknown Component'
+ }
+ return {
+ _custom: {
+ type: 'component-definition',
+ display,
+ tooltip: 'Component definition',
+ ...def.__file
+ ? {
+ file: def.__file,
+ }
+ : {},
+ },
+ }
+}
+
+export function getCustomFunctionDetails(func: Function): CustomState {
+ let string = ''
+ let matches = null
+ try {
+ string = Function.prototype.toString.call(func)
+ matches = String.prototype.match.call(string, /\([\s\S]*?\)/)
+ }
+ catch (e) {
+ // Func is probably a Proxy, which can break Function.prototype.toString()
+ }
+ // Trim any excess whitespace from the argument string
+ const match = matches && matches[0]
+ const args = typeof match === 'string'
+ ? match
+ : '(?)'
+ const name = typeof func.name === 'string' ? func.name : ''
+ return {
+ _custom: {
+ type: 'function',
+ display: `function ${escape(name)}${args}`,
+ tooltip: string.trim() ? `${string}
` : null,
+ _reviveId: reviveCache.cache(func),
+ },
+ }
+}
+
+export function getCustomHTMLElementDetails(value: HTMLElement): CustomState {
+ try {
+ return {
+ _custom: {
+ type: 'HTMLElement',
+ display: `<${value.tagName.toLowerCase()}>`,
+ value: namedNodeMapToObject(value.attributes),
+ actions: [
+ {
+ icon: 'input',
+ tooltip: 'Log element to console',
+ action: () => {
+ // eslint-disable-next-line no-console
+ console.log(value)
+ },
+ },
+ ],
+ },
+ }
+ }
+ catch (e) {
+ return {
+ _custom: {
+ type: 'HTMLElement',
+ display: `${String(value)}`,
+ },
+ }
+ }
+}
+
+function namedNodeMapToObject(map: NamedNodeMap) {
+ const result: any = {}
+ const l = map.length
+ for (let i = 0; i < l; i++) {
+ const node = map.item(i)
+ result[node.name] = node.value
+ }
+ return result
+}
+
+export function getCustomRefDetails(instance, key, ref) {
+ let value
+ if (Array.isArray(ref)) {
+ value = ref.map(r => getCustomRefDetails(instance, key, r)).map(data => data.value)
+ }
+ else {
+ let name
+ if (ref._isVue) {
+ name = getComponentName(ref.$options)
+ }
+ else {
+ name = ref.tagName.toLowerCase()
+ }
+
+ value = {
+ _custom: {
+ display: `<${name}${
+ ref.id ? ` id="${ref.id}"` : ''
+ }${ref.className ? ` class="${ref.className}"` : ''}>`,
+ uid: instance.__VUE_DEVTOOLS_UID__,
+ type: 'reference',
+ },
+ }
+ }
+ return {
+ type: '$refs',
+ key,
+ value,
+ editable: false,
+ }
+}
+
+export function parse(data: any, revive = false) {
+ return revive
+ ? parseCircularAutoChunks(data, reviver)
+ : parseCircularAutoChunks(data)
+}
+
+const specialTypeRE = /^\[native (\w+) (.*?)(?:<>[.\s]*)?\]$/
+const symbolRE = /^\[native Symbol Symbol\((.*)\)\]$/
+
+function reviver(key, val) {
+ return revive(val)
+}
+
+export function revive(val) {
+ if (val === UNDEFINED) {
+ return undefined
+ }
+ else if (val === INFINITY) {
+ return Number.POSITIVE_INFINITY
+ }
+ else if (val === NEGATIVE_INFINITY) {
+ return Number.NEGATIVE_INFINITY
+ }
+ else if (val === NAN) {
+ return Number.NaN
+ }
+ else if (val && val._custom) {
+ const { _custom: custom }: CustomState = val
+ if (custom.type === 'component') {
+ return getInstanceMap().get(custom.id)
+ }
+ else if (custom.type === 'map') {
+ return reviveMap(val)
+ }
+ else if (custom.type === 'set') {
+ return reviveSet(val)
+ }
+ else if (custom.type === 'bigint') {
+ return BigInt(custom.value)
+ }
+ else if (custom.type === 'date') {
+ return new Date(custom.value)
+ }
+ else if (custom._reviveId) {
+ return reviveCache.read(custom._reviveId)
+ }
+ else {
+ return revive(custom.value)
+ }
+ }
+ else if (symbolRE.test(val)) {
+ const [, string] = symbolRE.exec(val)
+ return Symbol.for(string)
+ }
+ else if (specialTypeRE.test(val)) {
+ const [, type, string,, details] = specialTypeRE.exec(val)
+ const result = new target[type](string)
+ if (type === 'Error' && details) {
+ result.stack = details
+ }
+ return result
+ }
+ else {
+ return val
+ }
+}
+
+/**
+ * Sanitize data to be posted to the other side.
+ * Since the message posted is sent with structured clone,
+ * we need to filter out any types that might cause an error.
+ *
+ * @param {*} data
+ * @return {*}
+ */
+
+function sanitize(data) {
+ if (
+ !isPrimitive(data)
+ && !Array.isArray(data)
+ && !isPlainObject(data)
+ ) {
+ // handle types that will probably cause issues in
+ // the structured clone
+ return Object.prototype.toString.call(data)
+ }
+ else {
+ return data
+ }
+}
+
+export function isPlainObject(obj) {
+ return Object.prototype.toString.call(obj) === '[object Object]'
+}
+
+function isPrimitive(data) {
+ if (data == null) {
+ return true
+ }
+ const type = typeof data
+ return (
+ type === 'string'
+ || type === 'number'
+ || type === 'boolean'
+ )
+}
+
+/**
+ * Searches a key or value in the object, with a maximum deepness
+ * @param {*} obj Search target
+ * @param {string} searchTerm Search string
+ * @returns {boolean} Search match
+ */
+export function searchDeepInObject(obj, searchTerm) {
+ const seen = new Map()
+ const result = internalSearchObject(obj, searchTerm.toLowerCase(), seen, 0)
+ seen.clear()
+ return result
+}
+
+const SEARCH_MAX_DEPTH = 10
+
+/**
+ * Executes a search on each field of the provided object
+ * @param {*} obj Search target
+ * @param {string} searchTerm Search string
+ * @param {Map} seen Map containing the search result to prevent stack overflow by walking on the same object multiple times
+ * @param {number} depth Deep search depth level, which is capped to prevent performance issues
+ * @returns {boolean} Search match
+ */
+function internalSearchObject(obj, searchTerm, seen, depth) {
+ if (depth > SEARCH_MAX_DEPTH) {
+ return false
+ }
+ let match = false
+ const keys = Object.keys(obj)
+ let key, value
+ for (let i = 0; i < keys.length; i++) {
+ key = keys[i]
+ value = obj[key]
+ match = internalSearchCheck(searchTerm, key, value, seen, depth + 1)
+ if (match) {
+ break
+ }
+ }
+ return match
+}
+
+/**
+ * Executes a search on each value of the provided array
+ * @param {*} array Search target
+ * @param {string} searchTerm Search string
+ * @param {Map} seen Map containing the search result to prevent stack overflow by walking on the same object multiple times
+ * @param {number} depth Deep search depth level, which is capped to prevent performance issues
+ * @returns {boolean} Search match
+ */
+function internalSearchArray(array, searchTerm, seen, depth) {
+ if (depth > SEARCH_MAX_DEPTH) {
+ return false
+ }
+ let match = false
+ let value
+ for (let i = 0; i < array.length; i++) {
+ value = array[i]
+ match = internalSearchCheck(searchTerm, null, value, seen, depth + 1)
+ if (match) {
+ break
+ }
+ }
+ return match
+}
+
+/**
+ * Checks if the provided field matches the search terms
+ * @param {string} searchTerm Search string
+ * @param {string} key Field key (null if from array)
+ * @param {*} value Field value
+ * @param {Map} seen Map containing the search result to prevent stack overflow by walking on the same object multiple times
+ * @param {number} depth Deep search depth level, which is capped to prevent performance issues
+ * @returns {boolean} Search match
+ */
+function internalSearchCheck(searchTerm, key, value, seen, depth) {
+ let match = false
+ let result
+ if (key === '_custom') {
+ key = value.display
+ value = value.value
+ }
+ (result = specialTokenToString(value)) && (value = result)
+ if (key && compare(key, searchTerm)) {
+ match = true
+ seen.set(value, true)
+ }
+ else if (seen.has(value)) {
+ match = seen.get(value)
+ }
+ else if (Array.isArray(value)) {
+ seen.set(value, null)
+ match = internalSearchArray(value, searchTerm, seen, depth)
+ seen.set(value, match)
+ }
+ else if (isPlainObject(value)) {
+ seen.set(value, null)
+ match = internalSearchObject(value, searchTerm, seen, depth)
+ seen.set(value, match)
+ }
+ else if (compare(value, searchTerm)) {
+ match = true
+ seen.set(value, true)
+ }
+ return match
+}
+
+/**
+ * Compares two values
+ * @param {*} value Mixed type value that will be cast to string
+ * @param {string} searchTerm Search string
+ * @returns {boolean} Search match
+ */
+function compare(value, searchTerm) {
+ return (`${value}`).toLowerCase().includes(searchTerm)
+}
+
+export function sortByKey(state) {
+ return state && state.slice().sort((a, b) => {
+ if (a.key < b.key) {
+ return -1
+ }
+ if (a.key > b.key) {
+ return 1
+ }
+ return 0
+ })
+}
+
+export function simpleGet(object, path) {
+ const sections = Array.isArray(path) ? path : path.split('.')
+ for (let i = 0; i < sections.length; i++) {
+ object = object[sections[i]]
+ if (!object) {
+ return undefined
+ }
+ }
+ return object
+}
+
+export function focusInput(el) {
+ el.focus()
+ el.setSelectionRange(0, el.value.length)
+}
+
+export function openInEditor(file) {
+ // Console display
+ const fileName = file.replace(/\\/g, '\\\\')
+ const src = `fetch('${SharedData.openInEditorHost}__open-in-editor?file=${encodeURI(file)}').then(response => {
+ if (response.ok) {
+ console.log('File ${fileName} opened in editor')
+ } else {
+ const msg = 'Opening component ${fileName} failed'
+ const target = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : {}
+ if (target.__VUE_DEVTOOLS_TOAST__) {
+ target.__VUE_DEVTOOLS_TOAST__(msg, 'error')
+ } else {
+ console.log('%c' + msg, 'color:red')
+ }
+ console.log('Check the setup of your project, see https://devtools.vuejs.org/guide/open-in-editor.html')
+ }
+ })`
+ if (isChrome) {
+ target.chrome.devtools.inspectedWindow.eval(src)
+ }
+ else {
+ // eslint-disable-next-line no-eval
+ eval(src)
+ }
+}
+
+const ESC = {
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ '&': '&',
+}
+
+export function escape(s) {
+ return s.replace(/[<>"&]/g, escapeChar)
+}
+
+function escapeChar(a) {
+ return ESC[a] || a
+}
+
+export function copyToClipboard(state) {
+ let text: string
+
+ if (typeof state !== 'object') {
+ text = String(state)
+ }
+ else {
+ text = stringify(state, 'user')
+ }
+
+ // @TODO navigator.clipboard is buggy in extensions
+ if (typeof document === 'undefined') {
+ return
+ }
+ const dummyTextArea = document.createElement('textarea')
+ dummyTextArea.textContent = text
+ document.body.appendChild(dummyTextArea)
+ dummyTextArea.select()
+ document.execCommand('copy')
+ document.body.removeChild(dummyTextArea)
+}
+
+export function isEmptyObject(obj) {
+ return obj === UNDEFINED || !obj || Object.keys(obj).length === 0
+}
+
+/**
+ * chunk an array into smaller chunk of given size.
+ * @see https://stackoverflow.com/a/37826698
+ * @param array
+ * @param size
+ */
+export function chunk(array: unknown[], size: number): unknown[][] {
+ return array.reduce((resultArray, item, index) => {
+ const chunkIndex = Math.floor(index / size)
+
+ if (!resultArray[chunkIndex]) {
+ resultArray[chunkIndex] = [] // start a new chunk
+ }
+
+ resultArray[chunkIndex].push(item)
+
+ return resultArray
+ }, []) as unknown[][]
+}
diff --git a/vue-devtools/packages/shared-utils/tsconfig.json b/vue-devtools/packages/shared-utils/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..0cbd10f3e673f806cf5c4f8b554e7501d234f848
--- /dev/null
+++ b/vue-devtools/packages/shared-utils/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "target": "ES2019",
+ "module": "CommonJS",
+ "moduleResolution": "Node",
+ "resolveJsonModule": true,
+ "types": [
+ "node",
+ "webpack-env"
+ ],
+ "strictBindCallApply": true,
+ "strictFunctionTypes": true,
+ "alwaysStrict": true,
+ // Strict
+ "noImplicitAny": false,
+ "noImplicitThis": true,
+ "sourceMap": true,
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "preserveWatchOutput": true
+ },
+ "include": [
+ "src/**/*"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/vue-devtools/packages/shell-chrome/devtools-background.html b/vue-devtools/packages/shell-chrome/devtools-background.html
new file mode 100644
index 0000000000000000000000000000000000000000..1de9677747be50e3ae981ec8ce2c679eb691e512
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/devtools-background.html
@@ -0,0 +1,2 @@
+
+
diff --git a/vue-devtools/packages/shell-chrome/devtools.html b/vue-devtools/packages/shell-chrome/devtools.html
new file mode 100644
index 0000000000000000000000000000000000000000..a791e60b77fe5ef642912af80e3ecc93972f159a
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/devtools.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-chrome/icons/128-beta.png b/vue-devtools/packages/shell-chrome/icons/128-beta.png
new file mode 100644
index 0000000000000000000000000000000000000000..a9642998d77ab097c511ec6a2aa3d9e405035f1e
Binary files /dev/null and b/vue-devtools/packages/shell-chrome/icons/128-beta.png differ
diff --git a/vue-devtools/packages/shell-chrome/icons/128-gray.png b/vue-devtools/packages/shell-chrome/icons/128-gray.png
new file mode 100644
index 0000000000000000000000000000000000000000..f78d5dbcd85b69d6c73666107045d355520b44a3
Binary files /dev/null and b/vue-devtools/packages/shell-chrome/icons/128-gray.png differ
diff --git a/vue-devtools/packages/shell-chrome/icons/128.nuxt.png b/vue-devtools/packages/shell-chrome/icons/128.nuxt.png
new file mode 100644
index 0000000000000000000000000000000000000000..fad57759a0eef1f3dfba4506f2668a5d6b19b627
Binary files /dev/null and b/vue-devtools/packages/shell-chrome/icons/128.nuxt.png differ
diff --git a/vue-devtools/packages/shell-chrome/icons/128.png b/vue-devtools/packages/shell-chrome/icons/128.png
new file mode 100644
index 0000000000000000000000000000000000000000..d0033f9afc2db03e92bb84d64e2672fcdf385dca
Binary files /dev/null and b/vue-devtools/packages/shell-chrome/icons/128.png differ
diff --git a/vue-devtools/packages/shell-chrome/icons/16-beta.png b/vue-devtools/packages/shell-chrome/icons/16-beta.png
new file mode 100644
index 0000000000000000000000000000000000000000..469c8e9212112ecde4467ddc91c8b38c8261b325
Binary files /dev/null and b/vue-devtools/packages/shell-chrome/icons/16-beta.png differ
diff --git a/vue-devtools/packages/shell-chrome/icons/16-gray.png b/vue-devtools/packages/shell-chrome/icons/16-gray.png
new file mode 100644
index 0000000000000000000000000000000000000000..4192c5e477248f34a39b1b1a38ab3a9425641c0b
Binary files /dev/null and b/vue-devtools/packages/shell-chrome/icons/16-gray.png differ
diff --git a/vue-devtools/packages/shell-chrome/icons/16.nuxt.png b/vue-devtools/packages/shell-chrome/icons/16.nuxt.png
new file mode 100644
index 0000000000000000000000000000000000000000..05e23ae4e920df740080cce1a68e162a8c1bafec
Binary files /dev/null and b/vue-devtools/packages/shell-chrome/icons/16.nuxt.png differ
diff --git a/vue-devtools/packages/shell-chrome/icons/16.png b/vue-devtools/packages/shell-chrome/icons/16.png
new file mode 100644
index 0000000000000000000000000000000000000000..2fcb5a47acbb7c6b41f09d71260df66420fe3c07
Binary files /dev/null and b/vue-devtools/packages/shell-chrome/icons/16.png differ
diff --git a/vue-devtools/packages/shell-chrome/icons/48-beta.png b/vue-devtools/packages/shell-chrome/icons/48-beta.png
new file mode 100644
index 0000000000000000000000000000000000000000..1c898eb89e19bcc1c09c1923c008d676e07fb0a4
Binary files /dev/null and b/vue-devtools/packages/shell-chrome/icons/48-beta.png differ
diff --git a/vue-devtools/packages/shell-chrome/icons/48-gray.png b/vue-devtools/packages/shell-chrome/icons/48-gray.png
new file mode 100644
index 0000000000000000000000000000000000000000..f1729d8fe15f475041f3dce2c792c0c7b7ebdf24
Binary files /dev/null and b/vue-devtools/packages/shell-chrome/icons/48-gray.png differ
diff --git a/vue-devtools/packages/shell-chrome/icons/48.nuxt.png b/vue-devtools/packages/shell-chrome/icons/48.nuxt.png
new file mode 100644
index 0000000000000000000000000000000000000000..7aa05062c14d98fa26208eb881c66314a6c4bb14
Binary files /dev/null and b/vue-devtools/packages/shell-chrome/icons/48.nuxt.png differ
diff --git a/vue-devtools/packages/shell-chrome/icons/48.png b/vue-devtools/packages/shell-chrome/icons/48.png
new file mode 100644
index 0000000000000000000000000000000000000000..95278785897f944c760d3b797dc9f07c3ab5a4dc
Binary files /dev/null and b/vue-devtools/packages/shell-chrome/icons/48.png differ
diff --git a/vue-devtools/packages/shell-chrome/manifest.json b/vue-devtools/packages/shell-chrome/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..d4e0b419b7c453a0a8b670e8a40f78726be030a5
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/manifest.json
@@ -0,0 +1,71 @@
+{
+ "name": "Vue.js devtools",
+ "version": "6.6.3",
+ "version_name": "6.6.3",
+ "description": "Browser DevTools extension for debugging Vue.js applications.",
+ "manifest_version": 3,
+ "icons": {
+ "16": "icons/16.png",
+ "48": "icons/48.png",
+ "128": "icons/128.png"
+ },
+ "action": {
+ "default_icon": {
+ "16": "icons/16-gray.png",
+ "48": "icons/48-gray.png",
+ "128": "icons/128-gray.png"
+ },
+ "default_title": "Vue Devtools",
+ "default_popup": "popups/not-found.html"
+ },
+ "web_accessible_resources": [
+ {
+ "resources": [
+ "devtools.html",
+ "devtools-background.html",
+ "build/backend.js",
+ "build/proxy.js",
+ "build/hook-exec.js",
+ "build/detector-exec.js"
+ ],
+ "matches": [
+ ""
+ ],
+ "extension_ids": []
+ }
+ ],
+ "devtools_page": "devtools-background.html",
+ "background": {
+ "service_worker": "build/service-worker.js"
+ },
+ "permissions": [
+ "storage",
+ "scripting"
+ ],
+ "host_permissions": [
+ ""
+ ],
+ "content_scripts": [
+ {
+ "matches": [
+ ""
+ ],
+ "js": [
+ "build/hook.js"
+ ],
+ "run_at": "document_start"
+ },
+ {
+ "matches": [
+ ""
+ ],
+ "js": [
+ "build/detector.js"
+ ],
+ "run_at": "document_idle"
+ }
+ ],
+ "content_security_policy": {
+ "extension_pages": "script-src 'self'; object-src 'self'"
+ }
+}
\ No newline at end of file
diff --git a/vue-devtools/packages/shell-chrome/package.json b/vue-devtools/packages/shell-chrome/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ec89326460e989b437536e716629b8237d5c4d8
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "@vue-devtools/shell-chrome",
+ "version": "0.0.0",
+ "scripts": {
+ "build": "rimraf ./build && cross-env NODE_ENV=production webpack --progress"
+ },
+ "dependencies": {
+ "@vue-devtools/app-backend-core": "^0.0.0",
+ "@vue-devtools/app-frontend": "^0.0.0",
+ "@vue-devtools/shared-utils": "^0.0.0"
+ },
+ "devDependencies": {
+ "@vue-devtools/build-tools": "^0.0.0",
+ "rimraf": "^3.0.2",
+ "webpack": "^5.90.1",
+ "webpack-cli": "^5.1.4"
+ }
+}
diff --git a/vue-devtools/packages/shell-chrome/popups/devtools-screenshot.png b/vue-devtools/packages/shell-chrome/popups/devtools-screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..2cf3e0e1a6044f604c3caf3ec29b26c996f0cf9c
Binary files /dev/null and b/vue-devtools/packages/shell-chrome/popups/devtools-screenshot.png differ
diff --git a/vue-devtools/packages/shell-chrome/popups/disabled.html b/vue-devtools/packages/shell-chrome/popups/disabled.html
new file mode 100644
index 0000000000000000000000000000000000000000..1e7841b162bdf06e8de488ed826338ca69498057
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/popups/disabled.html
@@ -0,0 +1,8 @@
+
+
+
+
+ Vue.js is detected on this page.
+ Devtools inspection is not available because it's in
+ production mode or explicitly disabled by the author.
+
diff --git a/vue-devtools/packages/shell-chrome/popups/disabled.nuxt.html b/vue-devtools/packages/shell-chrome/popups/disabled.nuxt.html
new file mode 100644
index 0000000000000000000000000000000000000000..0a8a8af3d7432b97bebf8014969c28f4a4004c39
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/popups/disabled.nuxt.html
@@ -0,0 +1,8 @@
+
+
+
+
+ Nuxt + Vue.js is detected on this page.
+ Devtools inspection is not available because it's in
+ production mode or explicitly disabled by the author.
+
diff --git a/vue-devtools/packages/shell-chrome/popups/enabled.html b/vue-devtools/packages/shell-chrome/popups/enabled.html
new file mode 100644
index 0000000000000000000000000000000000000000..a8ac2725f5ca5d44eba9bafa5eb4f7d14b0449d1
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/popups/enabled.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+

+
+
+
+
+ Vue.js is detected on this page.
+ Open DevTools and look for the Vue panel.
+
+
+
+ Troubleshooting
+
+
+
diff --git a/vue-devtools/packages/shell-chrome/popups/enabled.nuxt.html b/vue-devtools/packages/shell-chrome/popups/enabled.nuxt.html
new file mode 100644
index 0000000000000000000000000000000000000000..a8ad11390dc89e2d5d331928feea0785f962b8b3
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/popups/enabled.nuxt.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+

+
+
+
+
+ Nuxt + Vue.js is detected on this page.
+ Open DevTools and look for the Vue panel.
+
+
+
+ Troubleshooting
+
+
+
diff --git a/vue-devtools/packages/shell-chrome/popups/not-found.html b/vue-devtools/packages/shell-chrome/popups/not-found.html
new file mode 100644
index 0000000000000000000000000000000000000000..39c5e9d38649ea3dd876ff43ae67d0c178520245
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/popups/not-found.html
@@ -0,0 +1,6 @@
+
+
+
+
+ Vue.js not detected
+
diff --git a/vue-devtools/packages/shell-chrome/popups/popup.css b/vue-devtools/packages/shell-chrome/popups/popup.css
new file mode 100644
index 0000000000000000000000000000000000000000..91a1e8bc3f61d658af3fa0e38de3782d143c6a51
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/popups/popup.css
@@ -0,0 +1,47 @@
+@import url('https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700,700i');
+
+body {
+ font-family: Roboto, Avenir, Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ font-weight: 400;
+ line-height: 1.4;
+ padding: 18px 24px;
+ color: #2c3e50;
+}
+
+body,
+p {
+ margin: 0;
+}
+
+p {
+ min-width: 200px;
+ max-width: 300px;
+}
+
+.short-paragraph {
+ min-width: initial;
+ white-space: nowrap;
+}
+
+a {
+ color: #42B983;
+}
+
+.flex {
+ display: flex;
+ align-items: center;
+}
+
+.screenshot {
+ position: relative;
+}
+
+.screenshot > img {
+ width: 140px;
+ height: 140px;
+ object-fit: cover;
+ border-radius: 100%;
+ margin-right: 24px;
+ box-shadow: 0 0 15px rgb(0 0 0 / 10%);
+}
diff --git a/vue-devtools/packages/shell-chrome/src/backend.js b/vue-devtools/packages/shell-chrome/src/backend.js
new file mode 100644
index 0000000000000000000000000000000000000000..d0456e1dd0ddeaf8982d9d462eee33ba69e84cd0
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/src/backend.js
@@ -0,0 +1,55 @@
+// this is injected to the app page when the panel is activated.
+
+import { initBackend } from '@back'
+import { Bridge } from '@vue-devtools/shared-utils'
+
+window.addEventListener('message', handshake)
+
+function sendListening() {
+ window.postMessage({
+ source: 'vue-devtools-backend-injection',
+ payload: 'listening',
+ }, '*')
+}
+sendListening()
+
+function handshake(e) {
+ if (e.data.source === 'vue-devtools-proxy' && e.data.payload === 'init') {
+ window.removeEventListener('message', handshake)
+
+ let listeners = []
+ const bridge = new Bridge({
+ listen(fn) {
+ const listener = (evt) => {
+ if (evt.data.source === 'vue-devtools-proxy' && evt.data.payload) {
+ fn(evt.data.payload)
+ }
+ }
+ window.addEventListener('message', listener)
+ listeners.push(listener)
+ },
+ send(data) {
+ // if (process.env.NODE_ENV !== 'production') {
+ // console.log('[chrome] backend -> devtools', data)
+ // }
+ window.postMessage({
+ source: 'vue-devtools-backend',
+ payload: data,
+ }, '*')
+ },
+ })
+
+ bridge.on('shutdown', () => {
+ listeners.forEach((l) => {
+ window.removeEventListener('message', l)
+ })
+ listeners = []
+ window.addEventListener('message', handshake)
+ })
+
+ initBackend(bridge)
+ }
+ else {
+ sendListening()
+ }
+}
diff --git a/vue-devtools/packages/shell-chrome/src/detector-exec.js b/vue-devtools/packages/shell-chrome/src/detector-exec.js
new file mode 100644
index 0000000000000000000000000000000000000000..da5f8813ec7e2e43c3932a1d4b2cb6f55b1a0137
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/src/detector-exec.js
@@ -0,0 +1,85 @@
+import { installToast } from '@back/toast'
+
+function sendMessage(message) {
+ window.postMessage({
+ key: '_vue-devtools-send-message',
+ message,
+ })
+}
+
+function detect() {
+ let delay = 1000
+ let detectRemainingTries = 10
+
+ function runDetect() {
+ // Method 1: Check Nuxt.js
+ const nuxtDetected = !!(window.__NUXT__ || window.$nuxt)
+
+ if (nuxtDetected) {
+ let Vue
+
+ if (window.$nuxt) {
+ Vue = window.$nuxt.$root && window.$nuxt.$root.constructor
+ }
+
+ sendMessage({
+ devtoolsEnabled: (/* Vue 2 */ Vue && Vue.config.devtools)
+ || (/* Vue 3.2.14+ */ window.__VUE_DEVTOOLS_GLOBAL_HOOK__ && window.__VUE_DEVTOOLS_GLOBAL_HOOK__.enabled),
+ vueDetected: true,
+ nuxtDetected: true,
+ }, '*')
+
+ return
+ }
+
+ // Method 2: Check Vue 3
+ const vueDetected = !!(window.__VUE__)
+ if (vueDetected) {
+ sendMessage({
+ devtoolsEnabled: /* Vue 3.2.14+ */ window.__VUE_DEVTOOLS_GLOBAL_HOOK__ && window.__VUE_DEVTOOLS_GLOBAL_HOOK__.enabled,
+ vueDetected: true,
+ }, '*')
+
+ return
+ }
+
+ // Method 3: Scan all elements inside document
+ const all = document.querySelectorAll('*')
+ let el
+ for (let i = 0; i < all.length; i++) {
+ if (all[i].__vue__) {
+ el = all[i]
+ break
+ }
+ }
+ if (el) {
+ let Vue = Object.getPrototypeOf(el.__vue__).constructor
+ while (Vue.super) {
+ Vue = Vue.super
+ }
+ sendMessage({
+ devtoolsEnabled: Vue.config.devtools,
+ vueDetected: true,
+ }, '*')
+ return
+ }
+
+ if (detectRemainingTries > 0) {
+ detectRemainingTries--
+ setTimeout(() => {
+ runDetect()
+ }, delay)
+ delay *= 5
+ }
+ }
+
+ setTimeout(() => {
+ runDetect()
+ }, 100)
+}
+
+// inject the hook
+if (document instanceof HTMLDocument) {
+ detect()
+ installToast()
+}
diff --git a/vue-devtools/packages/shell-chrome/src/detector.js b/vue-devtools/packages/shell-chrome/src/detector.js
new file mode 100644
index 0000000000000000000000000000000000000000..9c6397312883b40b61ee5d5733136da2ca90b8cf
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/src/detector.js
@@ -0,0 +1,12 @@
+window.addEventListener('message', (event) => {
+ if (event.data.key === '_vue-devtools-send-message') {
+ chrome.runtime.sendMessage(event.data.message)
+ }
+}, false)
+
+const script = document.createElement('script')
+script.src = chrome.runtime.getURL('build/detector-exec.js')
+script.onload = () => {
+ script.remove()
+}
+;(document.head || document.documentElement).appendChild(script)
diff --git a/vue-devtools/packages/shell-chrome/src/devtools-background.js b/vue-devtools/packages/shell-chrome/src/devtools-background.js
new file mode 100644
index 0000000000000000000000000000000000000000..69aeb183b2878cdfa5b8b9328a5d5d638db3be5f
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/src/devtools-background.js
@@ -0,0 +1,48 @@
+// This is the devtools script, which is called when the user opens the
+// Chrome devtool on a page. We check to see if we global hook has detected
+// Vue presence on the page. If yes, create the Vue panel; otherwise poll
+// for 10 seconds.
+
+let created = false
+let checkCount = 0
+
+chrome.devtools.network.onNavigated.addListener(createPanelIfHasVue)
+const checkVueInterval = setInterval(createPanelIfHasVue, 1000)
+createPanelIfHasVue()
+
+function createPanelIfHasVue() {
+ if (created || checkCount++ > 10) {
+ clearInterval(checkVueInterval)
+ return
+ }
+ chrome.devtools.inspectedWindow.eval(
+ '!!(window.__VUE_DEVTOOLS_GLOBAL_HOOK__ && (window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue || window.__VUE_DEVTOOLS_GLOBAL_HOOK__.apps.length))',
+ (hasVue) => {
+ if (!hasVue || created) {
+ return
+ }
+ clearInterval(checkVueInterval)
+ created = true
+ chrome.devtools.panels.create(
+ 'Vue',
+ 'icons/128.png',
+ 'devtools.html',
+ (panel) => {
+ // panel loaded
+ panel.onShown.addListener(onPanelShown)
+ panel.onHidden.addListener(onPanelHidden)
+ },
+ )
+ },
+ )
+}
+
+// Manage panel visibility
+
+function onPanelShown() {
+ chrome.runtime.sendMessage('vue-panel-shown')
+}
+
+function onPanelHidden() {
+ chrome.runtime.sendMessage('vue-panel-hidden')
+}
diff --git a/vue-devtools/packages/shell-chrome/src/devtools.js b/vue-devtools/packages/shell-chrome/src/devtools.js
new file mode 100644
index 0000000000000000000000000000000000000000..a18aca85eec50495a4eb31e91a8b683bb92b244d
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/src/devtools.js
@@ -0,0 +1,115 @@
+// this script is called when the VueDevtools panel is activated.
+
+import { initDevTools, setAppConnected } from '@front'
+import { Bridge, BridgeEvents } from '@vue-devtools/shared-utils'
+
+let disconnected = false
+let connectCount = 0
+let retryConnectTimer
+
+initDevTools({
+
+ /**
+ * Inject backend, connect to background, and send back the bridge.
+ *
+ * @param {Function} cb
+ */
+
+ connect(cb) {
+ // 1. inject backend code into page
+ injectScript(chrome.runtime.getURL('build/backend.js'), () => {
+ // 2. connect to background to setup proxy
+ let port
+
+ const onMessageHandlers = []
+
+ function connect() {
+ try {
+ clearTimeout(retryConnectTimer)
+ connectCount++
+ port = chrome.runtime.connect({
+ name: `${chrome.devtools.inspectedWindow.tabId}`,
+ })
+ disconnected = false
+ port.onDisconnect.addListener(() => {
+ disconnected = true
+ setAppConnected(false)
+
+ // Retry
+ retryConnectTimer = setTimeout(connect, 500)
+ })
+
+ if (connectCount > 1) {
+ onMessageHandlers.forEach(fn => port.onMessage.addListener(fn))
+ }
+ }
+ catch (e) {
+ console.error(e)
+ disconnected = true
+ setAppConnected(false)
+
+ // Retry
+ retryConnectTimer = setTimeout(connect, 1000)
+ }
+ }
+ connect()
+
+ const bridge = new Bridge({
+ listen(fn) {
+ port.onMessage.addListener(fn)
+ onMessageHandlers.push(fn)
+ },
+ send(data) {
+ if (!disconnected) {
+ // if (process.env.NODE_ENV !== 'production') {
+ // console.log('[chrome] devtools -> backend', data)
+ // }
+ port.postMessage(data)
+ }
+ },
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_RECONNECTED, () => {
+ setAppConnected(true)
+ })
+
+ // 3. send a proxy API to the panel
+ cb(bridge)
+ })
+ },
+
+ /**
+ * Register a function to reload the devtools app.
+ *
+ * @param {Function} reloadFn
+ */
+
+ onReload(reloadFn) {
+ chrome.devtools.network.onNavigated.addListener(reloadFn)
+ },
+})
+
+/**
+ * Inject a globally evaluated script, in the same context with the actual
+ * user app.
+ *
+ * @param {string} scriptName
+ * @param {Function} cb
+ */
+
+function injectScript(scriptName, cb) {
+ const src = `
+ (function() {
+ var script = document.constructor.prototype.createElement.call(document, 'script');
+ script.src = "${scriptName}";
+ document.documentElement.appendChild(script);
+ script.parentNode.removeChild(script);
+ })()
+ `
+ chrome.devtools.inspectedWindow.eval(src, (res, err) => {
+ if (err) {
+ console.error(err)
+ }
+ cb()
+ })
+}
diff --git a/vue-devtools/packages/shell-chrome/src/hook-exec.js b/vue-devtools/packages/shell-chrome/src/hook-exec.js
new file mode 100644
index 0000000000000000000000000000000000000000..7549d0f1680ea57e63532157a23d3551096b1079
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/src/hook-exec.js
@@ -0,0 +1,3 @@
+import { installHook } from '@back/hook'
+
+installHook(window)
diff --git a/vue-devtools/packages/shell-chrome/src/hook.js b/vue-devtools/packages/shell-chrome/src/hook.js
new file mode 100644
index 0000000000000000000000000000000000000000..16269d7e34059f76424ef26015ec4bb42b0335ac
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/src/hook.js
@@ -0,0 +1,6 @@
+const script = document.createElement('script')
+script.src = chrome.runtime.getURL('build/hook-exec.js')
+script.onload = () => {
+ script.remove()
+}
+;(document.head || document.documentElement).appendChild(script)
diff --git a/vue-devtools/packages/shell-chrome/src/proxy.js b/vue-devtools/packages/shell-chrome/src/proxy.js
new file mode 100644
index 0000000000000000000000000000000000000000..cb7e0e88abd90f2d66619e6725305b3808518ddf
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/src/proxy.js
@@ -0,0 +1,37 @@
+// This is a content-script that is injected only when the devtools are
+// activated. Because it is not injected using eval, it has full privilege
+// to the chrome runtime API. It serves as a proxy between the injected
+// backend and the Vue devtools panel.
+
+const port = chrome.runtime.connect({
+ name: 'content-script',
+})
+
+port.onMessage.addListener(sendMessageToBackend)
+window.addEventListener('message', sendMessageToDevtools)
+port.onDisconnect.addListener(handleDisconnect)
+
+sendMessageToBackend('init')
+
+function sendMessageToBackend(payload) {
+ window.postMessage({
+ source: 'vue-devtools-proxy',
+ payload,
+ }, '*')
+}
+
+function sendMessageToDevtools(e) {
+ if (e.data && e.data.source === 'vue-devtools-backend') {
+ port.postMessage(e.data.payload)
+ }
+ else if (e.data && e.data.source === 'vue-devtools-backend-injection') {
+ if (e.data.payload === 'listening') {
+ sendMessageToBackend('init')
+ }
+ }
+}
+
+function handleDisconnect() {
+ window.removeEventListener('message', sendMessageToDevtools)
+ sendMessageToBackend('shutdown')
+}
diff --git a/vue-devtools/packages/shell-chrome/src/service-worker.js b/vue-devtools/packages/shell-chrome/src/service-worker.js
new file mode 100644
index 0000000000000000000000000000000000000000..32fdaedb5d7a521491b4c51d2fa206554a38138e
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/src/service-worker.js
@@ -0,0 +1,130 @@
+// the background script runs all the time and serves as a central message
+// hub for each vue devtools (panel + proxy + backend) instance.
+
+const ports = {}
+
+chrome.runtime.onConnect.addListener((port) => {
+ let tab
+ let name
+ if (isNumeric(port.name)) {
+ tab = port.name
+ name = 'devtools'
+ installProxy(+port.name)
+ }
+ else {
+ tab = port.sender.tab.id
+ name = 'backend'
+ }
+
+ if (!ports[tab]) {
+ ports[tab] = {
+ devtools: null,
+ backend: null,
+ }
+ }
+ ports[tab][name] = port
+
+ if (ports[tab].devtools && ports[tab].backend) {
+ doublePipe(tab, ports[tab].devtools, ports[tab].backend)
+ }
+})
+
+function isNumeric(str) {
+ return `${+str}` === str
+}
+
+function installProxy(tabId) {
+ chrome.scripting.executeScript({
+ target: { tabId },
+ files: ['build/proxy.js'],
+ }, (res) => {
+ if (!res) {
+ ports[tabId].devtools.postMessage('proxy-fail')
+ }
+ else {
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log(`injected proxy to tab ${tabId}`)
+ }
+ }
+ })
+}
+
+function doublePipe(id, one, two) {
+ one.onMessage.addListener(lOne)
+ function lOne(message) {
+ if (message.event === 'log') {
+ // eslint-disable-next-line no-console
+ return console.log(`tab ${id}`, message.payload)
+ }
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log('%cdevtools -> backend', 'color:#888;', message)
+ }
+ two.postMessage(message)
+ }
+ two.onMessage.addListener(lTwo)
+ function lTwo(message) {
+ if (message.event === 'log') {
+ // eslint-disable-next-line no-console
+ return console.log(`tab ${id}`, message.payload)
+ }
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log('%cbackend -> devtools', 'color:#888;', message)
+ }
+ one.postMessage(message)
+ }
+ function shutdown() {
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log(`tab ${id} disconnected.`)
+ }
+ one.onMessage.removeListener(lOne)
+ two.onMessage.removeListener(lTwo)
+ one.disconnect()
+ two.disconnect()
+ ports[id] = null
+ }
+ one.onDisconnect.addListener(shutdown)
+ two.onDisconnect.addListener(shutdown)
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log(`tab ${id} connected.`)
+ }
+}
+
+chrome.runtime.onMessage.addListener((req, sender) => {
+ if (sender.tab && req.vueDetected) {
+ const suffix = req.nuxtDetected ? '.nuxt' : ''
+
+ chrome.action.setIcon({
+ tabId: sender.tab.id,
+ path: {
+ 16: chrome.runtime.getURL(`icons/16${suffix}.png`),
+ 48: chrome.runtime.getURL(`icons/48${suffix}.png`),
+ 128: chrome.runtime.getURL(`icons/128${suffix}.png`),
+ },
+ }, () => {
+ // noop
+ })
+ chrome.action.setPopup({
+ tabId: sender.tab.id,
+ popup: chrome.runtime.getURL(req.devtoolsEnabled ? `popups/enabled${suffix}.html` : `popups/disabled${suffix}.html`),
+ }, () => {
+ // noop
+ })
+ }
+
+ if (req.action === 'vue-take-screenshot' && sender.envType === 'devtools_child') {
+ browser.tabs.captureVisibleTab({
+ format: 'png',
+ }).then((dataUrl) => {
+ browser.runtime.sendMessage({
+ action: 'vue-screenshot-result',
+ id: req.id,
+ dataUrl,
+ })
+ })
+ }
+})
diff --git a/vue-devtools/packages/shell-chrome/webpack.config.js b/vue-devtools/packages/shell-chrome/webpack.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..ad00f1ee8d74da26ddccb9db644595998dfa60b9
--- /dev/null
+++ b/vue-devtools/packages/shell-chrome/webpack.config.js
@@ -0,0 +1,23 @@
+const path = require('node:path')
+const { createConfig } = require('@vue-devtools/build-tools')
+
+module.exports = createConfig({
+ entry: {
+ 'hook': './src/hook.js',
+ 'hook-exec': './src/hook-exec.js',
+ 'devtools': './src/devtools.js',
+ 'service-worker': './src/service-worker.js',
+ 'devtools-background': './src/devtools-background.js',
+ 'backend': './src/backend.js',
+ 'proxy': './src/proxy.js',
+ 'detector': './src/detector.js',
+ 'detector-exec': './src/detector-exec.js',
+ },
+ output: {
+ path: path.join(__dirname, 'build'),
+ filename: '[name].js',
+ },
+ devtool: process.env.NODE_ENV !== 'production'
+ ? 'inline-source-map'
+ : false,
+})
diff --git a/vue-devtools/packages/shell-dev-vue2/package.json b/vue-devtools/packages/shell-dev-vue2/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..8db2857751e6464c744be84540a596f53ddb8ba0
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "@vue-devtools/shell-dev-vue2",
+ "version": "0.0.0",
+ "private": true,
+ "scripts": {
+ "dev": "cross-env TAILWIND_MODE=watch PORT=8100 webpack serve"
+ },
+ "dependencies": {
+ "@vue-devtools/shell-host": "^0.0.0",
+ "vue": "^2.7.10",
+ "vue-router": "^3.6.5",
+ "vuex": "^3.6.2"
+ },
+ "devDependencies": {
+ "@vue-devtools/build-tools": "^0.0.0",
+ "cross-env": "^5.2.0",
+ "launch-editor-middleware": "^2.2.1",
+ "vue-loader": "^15.7.1",
+ "webpack": "^5.90.1",
+ "webpack-cli": "^5.1.4"
+ }
+}
diff --git a/vue-devtools/packages/shell-dev-vue2/public/target-electron.html b/vue-devtools/packages/shell-dev-vue2/public/target-electron.html
new file mode 100644
index 0000000000000000000000000000000000000000..c6c59bd5a2e9073bd15fd2712794ea15c6ed5948
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/public/target-electron.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/public/target-iframe.html b/vue-devtools/packages/shell-dev-vue2/public/target-iframe.html
new file mode 100644
index 0000000000000000000000000000000000000000..a52924bd2f2a692164f036b45d3e6d1fc5ecf5c4
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/public/target-iframe.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/public/target.html b/vue-devtools/packages/shell-dev-vue2/public/target.html
new file mode 100644
index 0000000000000000000000000000000000000000..1528f888c6d23a88005a9e60f6dd67a6884f9b65
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/public/target.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/Child.vue b/vue-devtools/packages/shell-dev-vue2/src/Child.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b09f6425c57054d03b38fb8c61cbe7faa7e7d2e0
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/Child.vue
@@ -0,0 +1,17 @@
+
+
+
+
+ {{ count }}
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/Counter.vue b/vue-devtools/packages/shell-dev-vue2/src/Counter.vue
new file mode 100644
index 0000000000000000000000000000000000000000..84d581a29e36fc62e9d9e76cc6f2a807ee549fa3
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/Counter.vue
@@ -0,0 +1,257 @@
+
+
+
+
+
{{ count }}
+
+
+
+
+
+
+
+
+
+
+
+
+
Your counter is {{ $store.getters.isPositive ? 'positive' : 'negative' }}
+
+
Vuex Module
+
+
+
foo: {{ foo }}
+
twoFoos: {{ twoFoos }}
+
+
+
+
+
+
+ {{ $store.state.dynamic }}
+ {{ $store.getters }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ $store.state.instant }}
+
+
{{ $store.state.deeplyNested }}
+
+
{{ $store.state.nested.nestedNested }}
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/EventChild.vue b/vue-devtools/packages/shell-dev-vue2/src/EventChild.vue
new file mode 100644
index 0000000000000000000000000000000000000000..56144779092216dcae6defeb8e457ab4e969e511
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/EventChild.vue
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/EventChild1.vue b/vue-devtools/packages/shell-dev-vue2/src/EventChild1.vue
new file mode 100644
index 0000000000000000000000000000000000000000..460865dd5f10a4b2d18ec3e7f6cb334dfad44ea6
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/EventChild1.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/EventChildCond.vue b/vue-devtools/packages/shell-dev-vue2/src/EventChildCond.vue
new file mode 100644
index 0000000000000000000000000000000000000000..6bd3b4eec88221fd257462d5804f2f5f8d3d1471
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/EventChildCond.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/Events.vue b/vue-devtools/packages/shell-dev-vue2/src/Events.vue
new file mode 100644
index 0000000000000000000000000000000000000000..88bb4b04d88240f268a2acb9299325f0e01046f5
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/Events.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
Events
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/Functional.vue b/vue-devtools/packages/shell-dev-vue2/src/Functional.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d1e97909e31f4ed0f9b31d1285ecc03a0d83a458
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/Functional.vue
@@ -0,0 +1,6 @@
+
+
+ Hello {{ props.name }}
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/Hidden.vue b/vue-devtools/packages/shell-dev-vue2/src/Hidden.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4f96f7170eb67e324dcd174f15cadc11bd9fe4ff
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/Hidden.vue
@@ -0,0 +1,11 @@
+
+
+
+ I'm hidden in the devtools
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/Init.vue b/vue-devtools/packages/shell-dev-vue2/src/Init.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1d31b18c4c264ca666f974aa972a79a61cda1a8b
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/Init.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/MyClass.js b/vue-devtools/packages/shell-dev-vue2/src/MyClass.js
new file mode 100644
index 0000000000000000000000000000000000000000..7260b4456d6490d367da4f9e4fa1e411cd959ba7
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/MyClass.js
@@ -0,0 +1,5 @@
+export default class MyClass {
+ constructor() {
+ this.msg = 'hi'
+ }
+}
diff --git a/vue-devtools/packages/shell-dev-vue2/src/NativeTypes.vue b/vue-devtools/packages/shell-dev-vue2/src/NativeTypes.vue
new file mode 100644
index 0000000000000000000000000000000000000000..48cd021bec906935c9075003a7ee902c9e18879d
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/NativeTypes.vue
@@ -0,0 +1,217 @@
+
+
+
+
+
Date: {{ date.toString() }} - Hours: {{ hours }} - Prototype: {{ date | prototypeString }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Large array size: {{ largeArray.length }}
+
+
+
Set
+
{{ setDisplay() }}
+
+
Map
+
{{ mapDisplay() }}
+
+
BigInt
+
{{ bigInt }}
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/NoProp.vue b/vue-devtools/packages/shell-dev-vue2/src/NoProp.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f57c4c1dcd9c491d40dc6edd69692504dfc72ce5
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/NoProp.vue
@@ -0,0 +1,13 @@
+
+
+
+ {{ someArray }}
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/Other.vue b/vue-devtools/packages/shell-dev-vue2/src/Other.vue
new file mode 100644
index 0000000000000000000000000000000000000000..5b99443543a6e080cda8630b92c178df6cf2bd90
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/Other.vue
@@ -0,0 +1,64 @@
+
+
+
+
+ Other {{ id }}
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/RefTester.vue b/vue-devtools/packages/shell-dev-vue2/src/RefTester.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b831afd2d6766aea966d9ce9d637cbe23c35a4a1
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/RefTester.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/Target.vue b/vue-devtools/packages/shell-dev-vue2/src/Target.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f7bc3d157d71086dff124978b233cdcf124df44e
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/Target.vue
@@ -0,0 +1,137 @@
+
+
+
+
+
{{ localMsg }} {{ msg }}
+
Regex: {{ regex.toString() }}
+
+
(Press enter to set)
+
+
+
+
+
+
+
+ Mouse over
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/TransitionExample.vue b/vue-devtools/packages/shell-dev-vue2/src/TransitionExample.vue
new file mode 100644
index 0000000000000000000000000000000000000000..19d8d7a55d857ccbf5ae577f58c7c0144868f852
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/TransitionExample.vue
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+ hello
+
+
+
+
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/VuexObject.vue b/vue-devtools/packages/shell-dev-vue2/src/VuexObject.vue
new file mode 100644
index 0000000000000000000000000000000000000000..dbec752f62dfc2b75457476daa16ff0e454fe07e
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/VuexObject.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
Vuex Object
+
{{ object }}
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/dynamic-module.js b/vue-devtools/packages/shell-dev-vue2/src/dynamic-module.js
new file mode 100644
index 0000000000000000000000000000000000000000..e8faf3edecdc3b82f8a43d914e43b991abc0200a
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/dynamic-module.js
@@ -0,0 +1,58 @@
+export const dynamic = {
+ namespaced: true,
+ state() {
+ return {
+ dynamic: true,
+ }
+ },
+ getters: {
+ notDynamic: (state) => {
+ if (state) {
+ return !state.dynamic
+ }
+ },
+ },
+ mutations: {
+ TOGGLE: (state) => {
+ state.dynamic = !state.dynamic
+ },
+ },
+}
+
+export const nested = {
+ namespaced: true,
+ state() {
+ return {
+ nested: true,
+ }
+ },
+ getters: {
+ notNested: (state) => {
+ if (state) {
+ return !state.nested
+ }
+ },
+ },
+ mutations: {
+ TOGGLE_NESTED: (state) => {
+ state.nested = !state.nested
+ },
+ },
+}
+
+export const deeplyNested = {
+ namespaced: true,
+ modules: {
+ child: {
+ namespaced: true,
+ state() {
+ return {
+ childMessage: 'hello from child',
+ }
+ },
+ getters: {
+ upercaseChildMessage: state => state.childMessage.toUpperCase(),
+ },
+ },
+ },
+}
diff --git a/vue-devtools/packages/shell-dev-vue2/src/iframe-app.js b/vue-devtools/packages/shell-dev-vue2/src/iframe-app.js
new file mode 100644
index 0000000000000000000000000000000000000000..08340cfde05c5c3ec8b45bbd0bf2d3f0603c5f6e
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/iframe-app.js
@@ -0,0 +1,7 @@
+import Vue from 'vue'
+import Child from './Child.vue'
+
+new Vue({
+ ...Child,
+ name: 'IframeApp',
+}).$mount('#app')
diff --git a/vue-devtools/packages/shell-dev-vue2/src/index.js b/vue-devtools/packages/shell-dev-vue2/src/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..73cf9dce0a780ca32b6eddf0152550374211d078
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/index.js
@@ -0,0 +1,95 @@
+import Vue from 'vue'
+import store from './store'
+import Target from './Target.vue'
+import Other from './Other.vue'
+import Init from './Init.vue'
+import Counter from './Counter.vue'
+import RefTester from './RefTester.vue'
+import VuexObject from './VuexObject.vue'
+import NativeTypes from './NativeTypes.vue'
+import Events from './Events.vue'
+import MyClass from './MyClass.js'
+import router from './router'
+import TransitionExample from './TransitionExample.vue'
+import Router from './router/Router.vue'
+import Hidden from './Hidden.vue'
+
+window.VUE_DEVTOOLS_CONFIG = {
+ openInEditorHost: '/',
+}
+
+const items = []
+for (let i = 0; i < 100; i++) {
+ items.push({ id: i })
+}
+
+const circular = {}
+circular.self = circular
+
+Vue.component('global', {
+ render: h => h('h3', 'Global component'),
+})
+
+const app = new Vue({
+ store,
+ router,
+ components: {
+ inline: {
+ render: h => h('h3', 'Inline component definition'),
+ },
+ },
+ data: {
+ obj: {
+ items,
+ circular,
+ },
+ },
+ render(h) {
+ return h('div', null, [
+ h(Counter),
+ h(Target, { props: { msg: 'hi', ins: new MyClass() } }),
+ h(Other),
+ h(Events, { key: 'foo' }),
+ h(NativeTypes, { key: new Date(), ref: 'nativeTypes' }),
+ h(Router, { key: [] }),
+ h(TransitionExample),
+ h(VuexObject),
+ h(Init),
+ h(RefTester),
+ h(Hidden),
+ h('global'),
+ h('inline'),
+ ])
+ },
+})
+
+window.addEventListener('load', () => {
+ app.$mount('#app')
+})
+
+const app2 = new Vue({
+ render(h) {
+ return h('div', null, [
+ h('h1', 'App 2'),
+ h(Other),
+ ])
+ },
+})
+app2.$mount('#app2')
+
+// custom element instance
+const ce = document.querySelector('#shadow')
+if (ce.attachShadow) {
+ const shadowRoot = ce.attachShadow({ mode: 'open' })
+
+ const ceVM = new Vue({
+ name: 'ShadowDom',
+ render(h) {
+ return h('h2', 'Inside Shadow DOM!')
+ },
+ }).$mount()
+
+ shadowRoot.appendChild(ceVM.$el)
+}
+
+window.top.document.title = 'Vue 2 Dev Shell'
diff --git a/vue-devtools/packages/shell-dev-vue2/src/router.js b/vue-devtools/packages/shell-dev-vue2/src/router.js
new file mode 100644
index 0000000000000000000000000000000000000000..86044a2d3dc4fe38b35389b2c72e139e21552856
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/router.js
@@ -0,0 +1,59 @@
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+import RouteOne from './router/RouteOne.vue'
+import RouteTwo from './router/RouteTwo.vue'
+import RouteWithParams from './router/RouteWithParams.vue'
+import NamedRoute from './router/NamedRoute.vue'
+import RouteWithQuery from './router/RouteWithQuery.vue'
+import RouteWithBeforeEnter from './router/RouteWithBeforeEnter.vue'
+import RouteWithAlias from './router/RouteWithAlias.vue'
+import RouteWithProps from './router/RouteWithProps.vue'
+import ParentRoute from './router/ParentRoute.vue'
+import ChildRoute from './router/ChildRoute.vue'
+
+Vue.use(VueRouter)
+
+const DynamicComponent = {
+ render: h => h('div', 'Hello from dynamic component'),
+}
+
+const routes = [
+ { path: '/route-one', component: RouteOne },
+ { path: '/route-two', component: RouteTwo },
+ { path: '/route-with-params/:username/:id', component: RouteWithParams },
+ { path: '/route-named', component: NamedRoute, name: 'NamedRoute' },
+ { path: '/route-with-query', component: RouteWithQuery },
+ {
+ path: '/route-with-before-enter',
+ component: RouteWithBeforeEnter,
+ beforeEnter: (to, from, next) => {
+ next()
+ },
+ },
+ { path: '/route-with-redirect', redirect: '/route-one' },
+ { path: '/route-with-redirect-function', redirect: () => '/route-one' },
+ { path: '/route-with-alias', component: RouteWithAlias, alias: '/this-is-the-alias' },
+ { path: '/route-with-dynamic-component', component: DynamicComponent, props: true },
+ {
+ path: '/route-with-props',
+ component: RouteWithProps,
+ props: {
+ username: 'My Username',
+ id: 99,
+ },
+ },
+ { path: '/route-with-props-default', component: RouteWithProps },
+ {
+ path: '/route-parent',
+ component: ParentRoute,
+ children: [
+ { path: '/route-child', component: ChildRoute },
+ ],
+ },
+]
+
+const router = new VueRouter({
+ routes,
+})
+
+export default router
diff --git a/vue-devtools/packages/shell-dev-vue2/src/router/ChildRoute.vue b/vue-devtools/packages/shell-dev-vue2/src/router/ChildRoute.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e36dd735e94c028c90007bcfdab42c526e535d41
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/router/ChildRoute.vue
@@ -0,0 +1,9 @@
+
+
+
+ Child route
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/router/NamedRoute.vue b/vue-devtools/packages/shell-dev-vue2/src/router/NamedRoute.vue
new file mode 100644
index 0000000000000000000000000000000000000000..2bfe542afa715c17e8bcd8108c58c8a5fce94749
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/router/NamedRoute.vue
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/router/ParentRoute.vue b/vue-devtools/packages/shell-dev-vue2/src/router/ParentRoute.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a31f026aa452e8cf1a7cb761a5ee6e0999c13418
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/router/ParentRoute.vue
@@ -0,0 +1,12 @@
+
+
+
+
+
Parent
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/router/RouteOne.vue b/vue-devtools/packages/shell-dev-vue2/src/router/RouteOne.vue
new file mode 100644
index 0000000000000000000000000000000000000000..76706842dd70d8fb6931a580bdddeccfa667341f
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/router/RouteOne.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/router/RouteTwo.vue b/vue-devtools/packages/shell-dev-vue2/src/router/RouteTwo.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a6734e7f66b7072a56a9905dafad774b05236aa6
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/router/RouteTwo.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithAlias.vue b/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithAlias.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c2f4fae1b2f3be6a4482fd92af97d233cd9a1ecc
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithAlias.vue
@@ -0,0 +1,10 @@
+
+
+
+
+
Hello from route with alias
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithBeforeEnter.vue b/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithBeforeEnter.vue
new file mode 100644
index 0000000000000000000000000000000000000000..94ae25a9fbedc25a6d83c9b50ca6a99d32d0e8f2
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithBeforeEnter.vue
@@ -0,0 +1,10 @@
+
+
+
+
+
Hello from before enter route
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithParams.vue b/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithParams.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f9be491865327ad4f1590a3977efa2421e4d00a0
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithParams.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
Hello from route with params: Username: {{ $route.params.username }}, Id: {{ $route.params.id }}
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithProps.vue b/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithProps.vue
new file mode 100644
index 0000000000000000000000000000000000000000..081618951272a8bfbe43f61fad5f8dfcca8814df
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithProps.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
Hello from route with props: Username: {{ username }}, Id: {{ id }}
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithQuery.vue b/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithQuery.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7f3580ed92fe975017aca993b7177565a7e4db46
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/router/RouteWithQuery.vue
@@ -0,0 +1,10 @@
+
+
+
+
+
Hello from route with query: {{ $route.query }}
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/router/Router.vue b/vue-devtools/packages/shell-dev-vue2/src/router/Router.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b6269d8490a809bbe06f3749110c35c18419f473
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/router/Router.vue
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+ Go to Route One
+
+
+
+
+ Go to Route Two
+
+
+
+
+ Go to route with params
+
+
+
+
+ Go to named route
+
+
+
+
+ Go to route with query
+
+
+
+
+ Go to route with before enter
+
+
+
+
+ Go to route with redirect
+
+
+
+
+ Go to route with alias
+
+
+
+
+ Go to route with dyn. component
+
+
+
+
+ Go to route with props
+
+
+
+
+ Go to route with props (default)
+
+
+
+
+ Go to route parent
+
+
+
+
+ Go to route child
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue2/src/store.js b/vue-devtools/packages/shell-dev-vue2/src/store.js
new file mode 100644
index 0000000000000000000000000000000000000000..5b058c6fec9c92dcb0b28ee9e313b63fbda496ab
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/src/store.js
@@ -0,0 +1,127 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+
+Vue.use(Vuex)
+
+export default new Vuex.Store({
+ strict: true,
+ state: {
+ inited: 0,
+ count: 0,
+ lastCountPayload: null,
+ date: new Date(),
+ set: new Set(),
+ map: new Map(),
+ sym: Symbol('test'),
+ object: {
+ name: 'I am Object',
+ number: 0,
+ children: [
+ {
+ number: 0,
+ },
+ ],
+ },
+ },
+ mutations: {
+ TEST_INIT: state => state.inited++,
+ INCREMENT: (state, payload) => {
+ state.count++
+ state.lastCountPayload = payload
+ },
+ DECREMENT: (state, payload) => {
+ state.count--
+ state.lastCountPayload = payload
+ },
+ UPDATE_DATE: (state) => {
+ state.date = new Date()
+ },
+ TEST_COMPONENT: (state) => { /* noop */ },
+ TEST_SET: (state) => {
+ state.set.add(Math.random())
+ },
+ TEST_MAP: (state) => {
+ state.map.set(`mykey_${state.map.size}`, state.map.size)
+ },
+ },
+ actions: {
+ ASYNC_INCREMENT: ({ commit }) => {
+ return wait(100).then(() => {
+ commit('INCREMENT', 1)
+ })
+ },
+ },
+ getters: {
+ isPositive: state => state.count >= 0,
+ hours: state => state.date.getHours(),
+ errorGetter: () => {
+ throw new Error('Error from getter')
+ },
+ },
+ modules: {
+ 'nested': {
+ namespaced: true,
+ state() {
+ return {
+ foo: 'bar',
+ }
+ },
+ getters: {
+ twoFoos: state => state.foo.repeat(2),
+ dummy: () => {
+ console.log('dummy getter was computed')
+ return 'dummy'
+ },
+ },
+ mutations: {
+ ADD_BAR: (state) => {
+ state.foo += 'bar'
+ },
+ REMOVE_BAR: (state) => {
+ state.foo = state.foo.substring('bar'.length)
+ },
+ },
+ modules: {
+ nestedNested: {
+ state() {
+ return {
+ answer: 42,
+ }
+ },
+ getters: {
+ doubleAnswer: state => state.answer * 2,
+ errorGetter: () => {
+ throw new Error('Error from getter')
+ },
+ },
+ },
+ },
+ },
+ 'notNamespaced': {
+ state() {
+ return {
+ hello: 'world',
+ }
+ },
+ getters: {
+ hello2: state => state.hello.repeat(2),
+ },
+ },
+ 'use/in/name': {
+ state() {
+ return {
+ meow: 'MEOW',
+ }
+ },
+ getters: {
+ meow2: state => state.meow.repeat(2),
+ },
+ },
+ },
+})
+
+function wait(ms) {
+ return new Promise((resolve) => {
+ setTimeout(resolve, ms)
+ })
+}
diff --git a/vue-devtools/packages/shell-dev-vue2/webpack.config.js b/vue-devtools/packages/shell-dev-vue2/webpack.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..4b841f3acb113c67f14b2837cbd1d653dd054e51
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue2/webpack.config.js
@@ -0,0 +1,54 @@
+const path = require('node:path')
+const { createConfig } = require('@vue-devtools/build-tools')
+const { VueLoaderPlugin } = require('vue-loader')
+
+const vueLoaderPath = require.resolve('vue-loader')
+const openInEditor = require('launch-editor-middleware')
+
+const config = createConfig({
+ entry: {
+ // devtools: require.resolve('@vue-devtools/shell-host/src/devtools.js'),
+ 'backend': require.resolve('@vue-devtools/shell-host/src/backend.js'),
+ 'hook': require.resolve('@vue-devtools/shell-host/src/hook.js'),
+ 'target': './src/index.js',
+ 'iframe-app': './src/iframe-app.js',
+ },
+ resolve: {
+ alias: {
+ vue: require.resolve('vue/dist/vue.esm.js'),
+ },
+ symlinks: false,
+ },
+ module: {
+ rules: [
+ {
+ test: /\.vue$/,
+ loader: vueLoaderPath,
+ options: {},
+ },
+ ],
+ },
+ output: {
+ path: path.join(__dirname, '/build'),
+ publicPath: '/target/',
+ filename: '[name].js',
+ },
+ devServer: {
+ onBeforeSetupMiddleware({ app }) {
+ app.use('/__open-in-editor', openInEditor())
+ },
+ proxy: {
+ '/': {
+ target: 'http://localhost:8091',
+ bypass: (req, res, proxyOptions) => {
+ if (req.url.startsWith('/target')) {
+ return req.url
+ }
+ },
+ },
+ },
+ },
+})
+
+config.plugins[0] = new VueLoaderPlugin()
+module.exports = config
diff --git a/vue-devtools/packages/shell-dev-vue3/package.json b/vue-devtools/packages/shell-dev-vue3/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..377225f580c05245325acd19be8aaa68262565a4
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "@vue-devtools/shell-dev-vue3",
+ "version": "0.0.0",
+ "private": true,
+ "scripts": {
+ "dev": "cross-env TAILWIND_MODE=watch webpack serve"
+ },
+ "dependencies": {
+ "@vue-devtools/shell-host": "^0.0.0",
+ "@vue/devtools-api": "^6.0.0-beta.1",
+ "core-js": "^3.6.4",
+ "vue": "^3.3.4",
+ "vue-router": "^4.2.5",
+ "vuex": "^4.0.1"
+ },
+ "devDependencies": {
+ "@vue-devtools/build-tools": "^0.0.0",
+ "@vue/compiler-sfc": "^3.3.4",
+ "cross-env": "^5.2.0",
+ "launch-editor-middleware": "^2.2.1",
+ "mini-css-extract-plugin": "^1.5.0",
+ "webpack": "^5.90.1",
+ "webpack-cli": "^5.1.4"
+ }
+}
diff --git a/vue-devtools/packages/shell-dev-vue3/public/target-iframe.html b/vue-devtools/packages/shell-dev-vue3/public/target-iframe.html
new file mode 100644
index 0000000000000000000000000000000000000000..a52924bd2f2a692164f036b45d3e6d1fc5ecf5c4
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/public/target-iframe.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/public/target.html b/vue-devtools/packages/shell-dev-vue3/public/target.html
new file mode 100644
index 0000000000000000000000000000000000000000..38a63f5e2189e886a5db13d57cbd1d9b0a3b8888
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/public/target.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/Animation.vue b/vue-devtools/packages/shell-dev-vue3/src/Animation.vue
new file mode 100644
index 0000000000000000000000000000000000000000..2035ca4c2597e3e67c82e78493a592c2655adfe1
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/Animation.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/App.vue b/vue-devtools/packages/shell-dev-vue3/src/App.vue
new file mode 100644
index 0000000000000000000000000000000000000000..dad906091561bf596e49996d615e16839ee85ad1
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/App.vue
@@ -0,0 +1,183 @@
+
+
+
+ Hello from Vue 3
+
+
+ {{ count }}
+
+ {{ text }}
+
+
+
+
+
+ {{ time }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Store
+
+ {{ $store.getters.answer }}
+
+ {{ $store.getters.twoFoo }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/App3.vue b/vue-devtools/packages/shell-dev-vue3/src/App3.vue
new file mode 100644
index 0000000000000000000000000000000000000000..dbde1815a931bd0121301afec749c14a9844bc74
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/App3.vue
@@ -0,0 +1,30 @@
+
+
+
+ App 3
+
+
+
+
+
+ {{ msg }}
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/AsyncComponent.vue b/vue-devtools/packages/shell-dev-vue3/src/AsyncComponent.vue
new file mode 100644
index 0000000000000000000000000000000000000000..3dbaf9a858abd29126459eae6bde99618e23ce16
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/AsyncComponent.vue
@@ -0,0 +1,27 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/AsyncSetup.vue b/vue-devtools/packages/shell-dev-vue3/src/AsyncSetup.vue
new file mode 100644
index 0000000000000000000000000000000000000000..dc7ca36e511996f99c71159b432346622c3ee59f
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/AsyncSetup.vue
@@ -0,0 +1,29 @@
+
+
+
+
+ Async setup:
+
{{ message }}
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/Child.vue b/vue-devtools/packages/shell-dev-vue3/src/Child.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4d6658a8912ea2ec4b2431074e3f753a538e1bd7
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/Child.vue
@@ -0,0 +1,84 @@
+
+
+
+
+ Child: {{ answer }} x2: {{ doubleAnswer }} x4: {{ reactiveObject.nestedComputed }}
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/Condition.vue b/vue-devtools/packages/shell-dev-vue3/src/Condition.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d17c44140e00840803a899754c37dae7a1f7776d
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/Condition.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/DomOrder.vue b/vue-devtools/packages/shell-dev-vue3/src/DomOrder.vue
new file mode 100644
index 0000000000000000000000000000000000000000..dae74f0bb4739ee18e46354e35f775b1fb590902
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/DomOrder.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/EventEmit.vue b/vue-devtools/packages/shell-dev-vue3/src/EventEmit.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a715fa9cb7aba55d39c9e4c52956d5f87b3e7918
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/EventEmit.vue
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/EventNesting.vue b/vue-devtools/packages/shell-dev-vue3/src/EventNesting.vue
new file mode 100644
index 0000000000000000000000000000000000000000..81f6941c496dc9cad8c0f9f93660ebd3ce6635f4
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/EventNesting.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/Form.vue b/vue-devtools/packages/shell-dev-vue3/src/Form.vue
new file mode 100644
index 0000000000000000000000000000000000000000..5063d91c88eff9db65cd09a10f397243dd1f7d2b
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/Form.vue
@@ -0,0 +1,34 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/FormSection.vue b/vue-devtools/packages/shell-dev-vue3/src/FormSection.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c9fa4766763a542e378086ee620759aa45a7d43e
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/FormSection.vue
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/Functional.vue b/vue-devtools/packages/shell-dev-vue3/src/Functional.vue
new file mode 100644
index 0000000000000000000000000000000000000000..9310b6e0dca2bdcfb833c2704e1b01f272d19160
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/Functional.vue
@@ -0,0 +1,14 @@
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/Ghost.vue b/vue-devtools/packages/shell-dev-vue3/src/Ghost.vue
new file mode 100644
index 0000000000000000000000000000000000000000..60cf2ba709daf8409bd978a119e596f3a6340982
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/Ghost.vue
@@ -0,0 +1,11 @@
+
+
+
+ I'm a ghost component that will be not displayed in the devtools
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/Heavy.vue b/vue-devtools/packages/shell-dev-vue3/src/Heavy.vue
new file mode 100644
index 0000000000000000000000000000000000000000..87e23bd8f9621daacf48901ef9a3f4c789706ce4
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/Heavy.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/Hello.vue b/vue-devtools/packages/shell-dev-vue3/src/Hello.vue
new file mode 100644
index 0000000000000000000000000000000000000000..85e3eeca1fdd12d502c58ec8fc581426d0ae8187
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/Hello.vue
@@ -0,0 +1,3 @@
+
+ Hello
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/IframeApp.vue b/vue-devtools/packages/shell-dev-vue3/src/IframeApp.vue
new file mode 100644
index 0000000000000000000000000000000000000000..64df44c23283a7747f2db27e5757d353c38bc983
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/IframeApp.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+ {{ msg }}
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/IndexComponent/index.vue b/vue-devtools/packages/shell-dev-vue3/src/IndexComponent/index.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a7e5dfc247159fe13ba212eaeb095fca375b6705
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/IndexComponent/index.vue
@@ -0,0 +1,3 @@
+
+ Index component
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/Mixins.vue b/vue-devtools/packages/shell-dev-vue3/src/Mixins.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4ac97f36bea4fbafc23409c09465f57018db66b5
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/Mixins.vue
@@ -0,0 +1,106 @@
+
+
+
+
+ {{ computedFromExtends }}
+
+ {{ computedFromMixin }}
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/NativeTypes.vue b/vue-devtools/packages/shell-dev-vue3/src/NativeTypes.vue
new file mode 100644
index 0000000000000000000000000000000000000000..06e7ee954dcca732ce5c591f9071c9e164ee18fb
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/NativeTypes.vue
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Large array size: {{ largeArray.length }}
+
+
+
Set
+
{{ setDisplay() }}
+
+
Map
+
{{ mapDisplay() }}
+
+
BigInt
+
{{ bigInt }}
+
+
Date
+
{{ localDate }}
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/Nested.vue b/vue-devtools/packages/shell-dev-vue3/src/Nested.vue
new file mode 100644
index 0000000000000000000000000000000000000000..309c6f52958a8f658393caed34130da8952a1b55
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/Nested.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+ Nest children
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/NestedMore.vue b/vue-devtools/packages/shell-dev-vue3/src/NestedMore.vue
new file mode 100644
index 0000000000000000000000000000000000000000..9fe35945c5e0256d1f266e1f1d1247ee984d4e18
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/NestedMore.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/Other.vue b/vue-devtools/packages/shell-dev-vue3/src/Other.vue
new file mode 100644
index 0000000000000000000000000000000000000000..6ae8dc71b7fbc26a7fee4010b5c35d9f8e89632f
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/Other.vue
@@ -0,0 +1,66 @@
+
+
+
+
+ Other {{ id }}
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/Provide.vue b/vue-devtools/packages/shell-dev-vue3/src/Provide.vue
new file mode 100644
index 0000000000000000000000000000000000000000..8cfaec04ca441804f90dda96e8541010e08032d6
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/Provide.vue
@@ -0,0 +1,51 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/SetupDataLike.vue b/vue-devtools/packages/shell-dev-vue3/src/SetupDataLike.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e9b8cb826724ef3d4a5f0fe1a5f62e509b776512
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/SetupDataLike.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/SetupRender.js b/vue-devtools/packages/shell-dev-vue3/src/SetupRender.js
new file mode 100644
index 0000000000000000000000000000000000000000..6f063885760d0c93c44dce15826704e3b3333924
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/SetupRender.js
@@ -0,0 +1,15 @@
+import { defineComponent, h, reactive } from 'vue'
+
+export default defineComponent({
+ name: 'SetupRender',
+
+ setup() {
+ const state = reactive({
+ name: 'Foo bar',
+ })
+
+ return () => {
+ return h('h1', state.name)
+ }
+ },
+})
diff --git a/vue-devtools/packages/shell-dev-vue3/src/SetupScript.vue b/vue-devtools/packages/shell-dev-vue3/src/SetupScript.vue
new file mode 100644
index 0000000000000000000000000000000000000000..883bd3335c64bc1cce2ef8219f35448fea40928a
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/SetupScript.vue
@@ -0,0 +1,46 @@
+
+
+
+ {{ count }}
+ {{ double }}
+
+
+
+
+
+ {{ state2 }}
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/SetupTSScriptProps.vue b/vue-devtools/packages/shell-dev-vue3/src/SetupTSScriptProps.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b190264be1731391afe055f00800659d59cf5fa1
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/SetupTSScriptProps.vue
@@ -0,0 +1,9 @@
+
+
+
+ {{ props }}
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/SuspenseExample.vue b/vue-devtools/packages/shell-dev-vue3/src/SuspenseExample.vue
new file mode 100644
index 0000000000000000000000000000000000000000..cca49b84b0f9f3a7995192cfadc8b7ebe0c14d43
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/SuspenseExample.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/VModelExample.vue b/vue-devtools/packages/shell-dev-vue3/src/VModelExample.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0d52e2ec06c2354b7016ee3725717e92da471837
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/VModelExample.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/devtools-plugin/index.js b/vue-devtools/packages/shell-dev-vue3/src/devtools-plugin/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..ed2cca8c0dd767a800e249923941ea333da34a3c
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/devtools-plugin/index.js
@@ -0,0 +1,368 @@
+import { setupDevtoolsPlugin } from '@vue/devtools-api'
+import { reactive, ref } from 'vue'
+
+/** @type {import('@vue/devtools-api').DevtoolsPluginApi} */
+let devtoolsApi
+
+const stateType = 'extra properties (test)'
+
+export default {
+ install: (app) => {
+ setupDevtoolsPlugin({
+ id: 'test-plugin',
+ label: 'Test devtools plugin',
+ packageName: '@vue/devtools-shell-dev-vue3',
+ homepage: 'https://github.com/vuejs/vue-devtools',
+ logo: 'https://nodepackjs.com/favicon.png',
+ componentStateTypes: [
+ stateType,
+ ],
+ enableEarlyProxy: true,
+ settings: {
+ test1: {
+ label: 'I like vue devtools',
+ type: 'boolean',
+ defaultValue: true,
+ },
+ test2: {
+ label: 'Quick choice',
+ type: 'choice',
+ defaultValue: 'a',
+ options: [
+ { value: 'a', label: 'A' },
+ { value: 'b', label: 'B' },
+ { value: 'c', label: 'C' },
+ ],
+ component: 'button-group',
+ },
+ test3: {
+ label: 'Long choice',
+ type: 'choice',
+ defaultValue: 'a',
+ options: [
+ { value: 'a', label: 'A' },
+ { value: 'b', label: 'B' },
+ { value: 'c', label: 'C' },
+ { value: 'd', label: 'D' },
+ { value: 'e', label: 'E' },
+ ],
+ },
+ test4: {
+ label: 'What is your name?',
+ type: 'text',
+ defaultValue: '',
+ },
+ },
+ app,
+ }, (api) => {
+ devtoolsApi = api
+
+ console.log('settings', api.getSettings())
+
+ const time = 0
+
+ api.on.visitComponentTree((payload, ctx) => {
+ const node = payload.treeNode
+ if (node.name === 'MyApp') {
+ node.tags.push({
+ label: 'root',
+ textColor: 0x000000,
+ backgroundColor: 0xFF984F,
+ })
+ }
+ else {
+ node.tags.push({
+ label: 'test',
+ textColor: 0xFFAAAA,
+ backgroundColor: 0xFFEEEE,
+ })
+ }
+ })
+
+ const componentState = {
+ foo: 'bar',
+ }
+
+ api.on.inspectComponent((payload, ctx) => {
+ if (payload.instanceData) {
+ payload.instanceData.state.push({
+ type: stateType,
+ key: 'foo',
+ value: componentState.foo,
+ editable: true,
+ })
+ payload.instanceData.state.push({
+ type: stateType,
+ key: 'time',
+ value: {
+ _custom: {
+ type: null,
+ readOnly: true,
+ display: `${time}s`,
+ tooltip: 'Elapsed time',
+ value: time,
+ },
+ },
+ })
+
+ payload.instanceData.state.push({
+ type: 'fail',
+ key: 'state',
+ editable: true,
+ value: reactive({ n: ref(0) }),
+ })
+
+ return api.getComponentBounds(payload.componentInstance).then((bounds) => {
+ payload.instanceData.state.push({
+ type: stateType,
+ key: 'bounds',
+ value: bounds
+ ? {
+ left: bounds.left,
+ top: bounds.top,
+ width: bounds.width,
+ height: bounds.height,
+ }
+ : null,
+ })
+ }).then(() => api.getComponentName(payload.componentInstance))
+ .then((name) => {
+ payload.instanceData.state.push({
+ type: stateType,
+ key: 'component name',
+ value: name,
+ })
+ })
+ }
+ })
+
+ api.on.editComponentState((payload) => {
+ if (payload.type === stateType) {
+ payload.set(componentState)
+ }
+ })
+
+ // setInterval(() => {
+ // time += 5
+ // // Update component
+ // api.notifyComponentUpdate()
+ // // Update custom inspector
+ // api.sendInspectorTree('test-inspector')
+ // api.sendInspectorState('test-inspector')
+ // }, 5000)
+
+ api.addTimelineLayer({
+ id: 'test-layer',
+ label: 'Test layer with a name far too long that should really be much shorter',
+ color: 0x92A2BF,
+ })
+
+ api.addTimelineEvent({
+ layerId: 'test-layer',
+ event: {
+ time: api.now(),
+ title: 'Early event',
+ data: {},
+ },
+ })
+
+ for (let i = 0; i < 10; i++) {
+ api.addTimelineLayer({
+ id: `test-layer-${i}`,
+ label: `Empty ${i}`,
+ color: 0x92A2BF,
+ })
+ }
+
+ api.on.inspectTimelineEvent((payload) => {
+ if (payload.layerId === 'test-layer') {
+ return new Promise((resolve) => {
+ payload.data = {
+ ...payload.data,
+ hey: 'hello',
+ }
+ setTimeout(resolve, 1000)
+ })
+ }
+ })
+
+ api.on.timelineCleared(() => {
+ console.log('timeline is cleared!')
+ })
+
+ api.addInspector({
+ id: 'test-inspector',
+ label: 'Test inspector',
+ icon: 'tab_unselected',
+ treeFilterPlaceholder: 'Search for test...',
+ noSelectionText: 'Select a node to view details',
+ actions: [
+ {
+ icon: 'star',
+ tooltip: 'Test custom action',
+ action: () => {
+ console.log('Meow! 🐱')
+ api.selectInspectorNode('test-inspector', 'child')
+ },
+ },
+ ],
+ nodeActions: [
+ {
+ icon: 'help',
+ tooltip: 'Test custom node action',
+ action: (arg1) => {
+ console.log('Node action', arg1)
+ api.selectInspectorNode('test-inspector', 'child')
+ },
+ },
+ ],
+ })
+
+ api.addInspector({
+ id: 'test-inspector2',
+ label: 'Test inspector 2',
+ })
+
+ let componentInstances = []
+
+ api.on.getInspectorTree((payload) => {
+ if (payload.inspectorId === 'test-inspector') {
+ payload.rootNodes = [
+ {
+ id: 'root',
+ label: `Root (${time})`,
+ children: [
+ {
+ id: 'child',
+ label: `Child ${payload.filter}`,
+ tags: [
+ {
+ label: 'active',
+ textColor: 0x000000,
+ backgroundColor: 0xFF984F,
+ },
+ {
+ label: 'test',
+ textColor: 0xFFFFFF,
+ backgroundColor: 0x000000,
+ },
+ ],
+ },
+ ],
+ },
+ ]
+ }
+ else if (payload.inspectorId === 'test-inspector2') {
+ return api.getComponentInstances(app).then((instances) => {
+ componentInstances = instances
+ for (const instance of instances) {
+ payload.rootNodes.push({
+ id: instance.uid.toString(),
+ label: `Component ${instance.uid}`,
+ })
+ }
+ })
+ }
+ })
+
+ const myState = {
+ foo: 'bar',
+ }
+
+ api.on.getInspectorState((payload) => {
+ if (payload.inspectorId === 'test-inspector') {
+ if (payload.nodeId === 'root') {
+ payload.state = {
+ 'root info': [
+ {
+ key: 'foo',
+ value: myState.foo,
+ editable: true,
+ },
+ {
+ key: 'time',
+ value: time,
+ },
+ ],
+ }
+ }
+ else {
+ payload.state = {
+ 'child info': [
+ {
+ key: 'answer',
+ value: {
+ _custom: {
+ display: '42!!!',
+ value: 42,
+ tooltip: 'The answer',
+ },
+ },
+ },
+ ],
+ }
+ }
+ }
+ else if (payload.inspectorId === 'test-inspector2') {
+ const instance = componentInstances.find(instance => instance.uid.toString() === payload.nodeId)
+ if (instance) {
+ api.unhighlightElement()
+ api.highlightElement(instance)
+ }
+ }
+ })
+
+ api.on.editInspectorState((payload) => {
+ if (payload.inspectorId === 'test-inspector') {
+ if (payload.nodeId === 'root') {
+ payload.set(myState)
+ }
+ }
+ })
+
+ // Plugin settings change
+ api.on.setPluginSettings((payload) => {
+ console.log('plugin settings changed', payload)
+ })
+ })
+
+ // Outside of setupDevtoolsPlugin
+
+ window.addEventListener('mouseup', (event) => {
+ devtoolsApi && devtoolsApi.addTimelineEvent({
+ layerId: 'test-layer',
+ event: {
+ time: devtoolsApi.now(),
+ data: {
+ info: 'window.mouseup',
+ x: event.clientX,
+ y: event.clientY,
+ },
+ logType: event.clientX < 100 ? 'error' : event.clientY < 100 ? 'warning' : 'default',
+ },
+ })
+ })
+
+ window.addEventListener('keydown', (event) => {
+ devtoolsApi && devtoolsApi.addTimelineEvent({
+ layerId: 'test-layer',
+ event: {
+ time: devtoolsApi.now(),
+ data: {
+ info: 'window.keyup',
+ key: event.key,
+ },
+ groupId: event.key,
+ title: 'Group test',
+ meta: {
+ foo: 'bar',
+ },
+ },
+ })
+
+ if (devtoolsApi && event.key === 's') {
+ console.log('settings', devtoolsApi.getSettings())
+ }
+ })
+ },
+}
diff --git a/vue-devtools/packages/shell-dev-vue3/src/devtools-plugin/simple.js b/vue-devtools/packages/shell-dev-vue3/src/devtools-plugin/simple.js
new file mode 100644
index 0000000000000000000000000000000000000000..c0ad3b8d982faa8fcef88b38e7733a931562722b
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/devtools-plugin/simple.js
@@ -0,0 +1,19 @@
+import { setupDevtoolsPlugin } from '@vue/devtools-api'
+
+export default {
+ install: (app) => {
+ setupDevtoolsPlugin({
+ id: 'simple-plugin',
+ label: 'Simple devtools plugin',
+ app,
+ }, (api) => {
+ api.on.visitComponentTree((payload, ctx) => {
+ payload.treeNode.tags.push({
+ label: 'simple plugin',
+ textColor: 0xFFAAAA,
+ backgroundColor: 0xFFEEEE,
+ })
+ })
+ })
+ },
+}
diff --git a/vue-devtools/packages/shell-dev-vue3/src/iframe-app.js b/vue-devtools/packages/shell-dev-vue3/src/iframe-app.js
new file mode 100644
index 0000000000000000000000000000000000000000..704d761324b67d17537acd8dae837dab889a4354
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/iframe-app.js
@@ -0,0 +1,4 @@
+import { createApp } from 'vue'
+import IframeApp from './IframeApp.vue'
+
+createApp(IframeApp).mount('#app')
diff --git a/vue-devtools/packages/shell-dev-vue3/src/main.js b/vue-devtools/packages/shell-dev-vue3/src/main.js
new file mode 100644
index 0000000000000000000000000000000000000000..a0fa435d71aff0ec1c6700dd7ae6417ef588939c
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/main.js
@@ -0,0 +1,68 @@
+import { createApp, h } from 'vue'
+import { createRouter, createWebHashHistory } from 'vue-router'
+import App from './App.vue'
+import App3 from './App3.vue'
+import TestPlugin from './devtools-plugin'
+import SimplePlugin from './devtools-plugin/simple'
+import store from './store'
+
+// eslint-disable-next-line no-extend-native
+Array.prototype.foo = 'bar'
+
+const router = createRouter({
+ history: createWebHashHistory(),
+
+ routes: [
+ {
+ path: '/p1',
+ component: import('./router/Page1.vue'),
+ },
+ {
+ path: '/p2',
+ component: import('./router/Page2.vue'),
+ },
+ ],
+})
+
+const app = createApp(App)
+app.component('global', {
+ render: () => 'I\'m a global component',
+})
+app.use(router)
+app.use(store)
+app.use(TestPlugin)
+app.mount('#app')
+
+const app2 = createApp({
+ name: 'App2',
+ render: () => h('h1', 'App 2'),
+})
+app2.mount('#app2')
+
+const app2bis = createApp({
+ name: 'App2',
+ render: () => h('h1', 'App 2 Bis'),
+})
+app2bis.mount('#app2bis')
+
+createApp(App3).mount('#app3')
+
+createApp({
+ render: () => h('button', {
+ onClick: () => app2.unmount(),
+ }, 'Remove app 2'),
+ devtools: {
+ hide: true,
+ },
+}).mount('#ghost-app')
+
+setTimeout(() => {
+ const app = createApp({
+ name: 'DelayedApp',
+ render: () => h('h1', 'Delayed app'),
+ })
+ app.use(SimplePlugin)
+ app.mount('#delay-app')
+}, 1000)
+
+window.top.document.title = 'Vue 3 Dev Shell'
diff --git a/vue-devtools/packages/shell-dev-vue3/src/router/Page1.vue b/vue-devtools/packages/shell-dev-vue3/src/router/Page1.vue
new file mode 100644
index 0000000000000000000000000000000000000000..5e8f033e480c6bad600062bd0bb2e1eecd736693
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/router/Page1.vue
@@ -0,0 +1,3 @@
+
+ Page 1
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/router/Page2.vue b/vue-devtools/packages/shell-dev-vue3/src/router/Page2.vue
new file mode 100644
index 0000000000000000000000000000000000000000..ee5bf13948c0abef9892cb4f7b761930dfb72d6b
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/router/Page2.vue
@@ -0,0 +1,3 @@
+
+ Page 2
+
diff --git a/vue-devtools/packages/shell-dev-vue3/src/store.js b/vue-devtools/packages/shell-dev-vue3/src/store.js
new file mode 100644
index 0000000000000000000000000000000000000000..0b7af0dc41043c3b7d8ab748b0b4a5811f267544
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/src/store.js
@@ -0,0 +1,60 @@
+import { createStore } from 'vuex'
+
+const store = createStore({
+ state() {
+ return {
+ rootState: 'root',
+ answer: 42,
+ }
+ },
+ getters: {
+ answer: state => state.answer,
+ throws: () => {
+ throw new Error('getter error')
+ },
+ },
+ mutations: {
+ increment(state) {
+ state.answer++
+ },
+ },
+ modules: {
+ nested: {
+ state() {
+ return {
+ foo: 'bar',
+ }
+ },
+ getters: {
+ twoFoo: state => state.foo.repeat(2),
+ },
+ },
+ namespacedModule: {
+ namespaced: true,
+ state() {
+ return {
+ count: 0,
+ }
+ },
+ getters: {
+ doubleCount: state => state.count * 2,
+ tripleCount: state => state.count * 3,
+ },
+ modules: {
+ animals: {
+ namespaced: true,
+ state() {
+ return {
+ cat: 'Meow',
+ }
+ },
+ getters: {
+ dog: () => 'Waf',
+ },
+ },
+ },
+ },
+ },
+})
+
+export default store
diff --git a/vue-devtools/packages/shell-dev-vue3/webpack.config.js b/vue-devtools/packages/shell-dev-vue3/webpack.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..47c9538a34388c8c558b9975970b395f6ff9a23c
--- /dev/null
+++ b/vue-devtools/packages/shell-dev-vue3/webpack.config.js
@@ -0,0 +1,37 @@
+const path = require('node:path')
+const openInEditor = require('launch-editor-middleware')
+const { createConfig } = require('@vue-devtools/build-tools')
+
+module.exports = createConfig({
+ context: __dirname,
+ entry: {
+ 'backend': require.resolve('@vue-devtools/shell-host/src/backend.js'),
+ 'hook': require.resolve('@vue-devtools/shell-host/src/hook.js'),
+ 'target': './src/main.js',
+ 'iframe-app': './src/iframe-app.js',
+ },
+ output: {
+ path: path.join(__dirname, '/build'),
+ publicPath: '/target/',
+ filename: '[name].js',
+ },
+ resolve: {
+ symlinks: false,
+ },
+ devServer: {
+ port: 8090,
+ onBeforeSetupMiddleware({ app }) {
+ app.use('/__open-in-editor', openInEditor())
+ },
+ proxy: {
+ '/': {
+ target: 'http://localhost:8091',
+ bypass: (req, res, proxyOptions) => {
+ if (req.url.startsWith('/target')) {
+ return req.url
+ }
+ },
+ },
+ },
+ },
+})
diff --git a/vue-devtools/packages/shell-electron/README.md b/vue-devtools/packages/shell-electron/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..cc1cf495f50c940a1dfb5560b2356c6f9d4a867f
--- /dev/null
+++ b/vue-devtools/packages/shell-electron/README.md
@@ -0,0 +1,157 @@
+# vue-remote-devtools
+
+> This package provides a standalone vue-devtools application, that can be used to debug any Vue app regardless of the environment. Now you can debug your app opened in mobile browser, safari, native script etc. not just desktop chrome or firefox.
+
+### :cd: Installation
+
+Install the package globally:
+```bash
+npm install -g @vue/devtools
+```
+
+Or locally as project dependency:
+```bash
+npm install --save-dev @vue/devtools
+```
+
+### :rocket: Usage
+
+#### Using global package
+
+Once you installed the package globally, run:
+```bash
+vue-devtools
+```
+
+Then add:
+```html
+
+```
+
+Or if you want to debug your device remotely:
+```html
+
+
+```
+
+To the `` section of your app.
+**(Don't forget to remove it before deploying to production!)**
+
+`` usually looks like this: `192.168.x.x`.
+
+#### Using dependency package
+
+Once you installed the package as project dependency, run:
+```bash
+./node_modules/.bin/vue-devtools
+```
+
+You can also use the global `vue-devtools` to start the app, but you might want to check if the local version matches the global one in this scenario to avoid any incompatibilities.
+
+Then import it directly in your app:
+```js
+import devtools from '@vue/devtools'
+// import Vue from 'vue'
+```
+> Make sure you import devtools before Vue, otherwise it might not work as expected.
+
+And connect to host:
+```js
+if (process.env.NODE_ENV === 'development') {
+ devtools.connect(/* host, port */)
+}
+```
+
+**host** - is an optional argument that tells your application where devtools middleware server is running, if you debug you app on your computer you don't have to set this (the default is `http://localhost`), but if you want to debug your app on mobile devices, you might want to pass your local IP (e.g. `http://192.168.1.12`).
+
+**port** - is an optional argument that tells your application on what port devtools middleware server is running. If you use proxy server, you might want to set it to `null` so the port won't be added to connection URL.
+
+#### FAQ:
+
+**1. How to change port devtools server is running on?**
+
+You can change it by setting environment variable before running it:
+```
+PORT=8000 vue-devtools
+```
+
+Then in your app you'll have to set either:
+```
+window.__VUE_DEVTOOLS_PORT__ = 8000
+```
+
+Or update connect method with new port:
+```
+devtools.connect(/* host */, 8000)
+```
+
+**2. How to remotely inspect page on the server?**
+
+For that you can use `ngrok` proxy. You can download it [here](https://ngrok.com/).
+
+Once you start vue-devtools run:
+```
+ngrok http 8098
+```
+
+Then update your host and port accordingly:
+```
+devtools.connect('https://example.ngrok.io', null)
+```
+
+Make sure to set port to `null` or `false`, because ngrok host already proxies to proper port that we defined in the first command.
+
+**3. How to inspect page served through `HTTPS`?**
+
+For that you can also use ngrok, as it automatically proxies https requests to http. Take a look at question number 2 for instructions.
+
+**4. How to inspect cordova applications?**
+
+Make sure that the page under `http://your-ip:8098` is returning a javascript coode on your device/simulator. If it doesn't - make sure to check your anti-virus or router/firewall settings. If it works - please follow the instructions, and connect to devtools using your IP. For example:
+
+```js
+import devtools from '@vue/devtools'
+import Vue from 'vue'
+// ...
+
+function onDeviceReady() {
+ devtools.connect('http://192.168.xx.yy') // use your IP
+}
+
+if (window.location.protocol === 'file:') {
+ document.addEventListener('deviceready', onDeviceReady, false)
+}
+else {
+ onDeviceReady()
+}
+```
+
+This will only work on `development` build of your app.
+
+### :beers: Development
+
+1. Install all dependencies
+```
+npm install
+```
+
+2. Run:
+```
+npm run dev
+```
+This will watch `src` folder and compile files on change
+
+3. Run:
+```
+npm start
+```
+This will open electron app with devtools
+
+4. Follow **Usage** section to connect any app to your development version of `vue-remote-devtools`
+
+### :lock: License
+
+[MIT](http://opensource.org/licenses/MIT)
diff --git a/vue-devtools/packages/shell-electron/app.html b/vue-devtools/packages/shell-electron/app.html
new file mode 100644
index 0000000000000000000000000000000000000000..2a207897c522e18a7f7be4aba92bbb765270ad15
--- /dev/null
+++ b/vue-devtools/packages/shell-electron/app.html
@@ -0,0 +1,113 @@
+
+
+
+
+ Vue Developer Tools
+
+
+
+
+

+
+ Waiting for connection...
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/packages/shell-electron/app.js b/vue-devtools/packages/shell-electron/app.js
new file mode 100644
index 0000000000000000000000000000000000000000..6757c25fe419aa4589702f2cf339ea85e62655f3
--- /dev/null
+++ b/vue-devtools/packages/shell-electron/app.js
@@ -0,0 +1,44 @@
+// Start middleware server
+require('./server')
+
+const path = require('node:path')
+const url = require('node:url')
+const { app, BrowserWindow } = require('electron')
+
+let mainWindow = null
+
+function createWindow() {
+ mainWindow = new BrowserWindow({
+ width: 800,
+ height: 600,
+ icon: path.join(__dirname, 'icons/128.png'),
+ webPreferences: {
+ nodeIntegration: true,
+ contextIsolation: false,
+ },
+ })
+
+ mainWindow.loadURL(url.format({
+ pathname: path.join(__dirname, 'app.html'),
+ protocol: 'file:',
+ slashes: true,
+ }))
+
+ mainWindow.on('closed', () => {
+ mainWindow = null
+ })
+}
+
+app.on('ready', createWindow)
+
+app.on('window-all-closed', () => {
+ if (process.platform !== 'darwin') {
+ app.quit()
+ }
+})
+
+app.on('activate', () => {
+ if (mainWindow === null) {
+ createWindow()
+ }
+})
diff --git a/vue-devtools/packages/shell-electron/bin.js b/vue-devtools/packages/shell-electron/bin.js
new file mode 100644
index 0000000000000000000000000000000000000000..6db275c810e50dcc7eec16acd72d5fc479d9ba23
--- /dev/null
+++ b/vue-devtools/packages/shell-electron/bin.js
@@ -0,0 +1,13 @@
+#!/usr/bin/env node
+const electron = require('electron')
+const spawn = require('cross-spawn')
+
+const argv = process.argv.slice(2)
+
+const result = spawn.sync(
+ electron,
+ [require.resolve('./app')].concat(argv),
+ { stdio: 'ignore' },
+)
+
+process.exit(result.status)
diff --git a/vue-devtools/packages/shell-electron/icons/128.png b/vue-devtools/packages/shell-electron/icons/128.png
new file mode 100644
index 0000000000000000000000000000000000000000..d0033f9afc2db03e92bb84d64e2672fcdf385dca
Binary files /dev/null and b/vue-devtools/packages/shell-electron/icons/128.png differ
diff --git a/vue-devtools/packages/shell-electron/index.js b/vue-devtools/packages/shell-electron/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..f32ad891f5590c3e5abae4c0466fed45bfa592a8
--- /dev/null
+++ b/vue-devtools/packages/shell-electron/index.js
@@ -0,0 +1,42 @@
+const isBrowser = typeof window !== 'undefined'
+
+if (isBrowser) {
+ require('./build/hook.js')
+}
+else {
+ require('./build-node/hook.js')
+}
+
+const target = isBrowser
+ ? window
+ : typeof globalThis !== 'undefined'
+ ? globalThis
+ : {}
+
+module.exports = {
+ connect(host, port, { io, showToast, app } = {}) {
+ target.__VUE_DEVTOOLS_HOST__ = host
+ target.__VUE_DEVTOOLS_PORT__ = port
+ if (io) {
+ target.__VUE_DEVTOOLS_SOCKET__ = io
+ }
+ if (showToast) {
+ target.__VUE_DEVTOOLS_TOAST__ = showToast
+ }
+ if (app) {
+ target.__VUE_ROOT_INSTANCES__ = Array.isArray(app) ? app : [app]
+ }
+
+ if (isBrowser) {
+ require('./build/backend.js')
+ }
+ else {
+ require('./build-node/backend.js')
+ }
+ },
+ init: (Vue) => {
+ const tools = target.__VUE_DEVTOOLS_GLOBAL_HOOK__
+
+ tools.emit('init', Vue)
+ },
+}
diff --git a/vue-devtools/packages/shell-electron/package.json b/vue-devtools/packages/shell-electron/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..c208dfc1fb15dfc2da92aecd0c3621e7aa96d5a1
--- /dev/null
+++ b/vue-devtools/packages/shell-electron/package.json
@@ -0,0 +1,59 @@
+{
+ "name": "@vue/devtools",
+ "version": "6.6.3",
+ "description": "StandAlone vue-devtools",
+ "author": "",
+ "license": "MIT",
+ "repository": {
+ "url": "https://github.com/vuejs/vue-devtools.git",
+ "type": "git",
+ "directory": "packages/shell-electron"
+ },
+ "sideEffects": false,
+ "main": "index.js",
+ "types": "types/index.d.ts",
+ "bin": {
+ "vue-devtools": "./bin.js"
+ },
+ "files": [
+ "README.md",
+ "app.html",
+ "app.js",
+ "bin.js",
+ "build",
+ "build-node",
+ "icons",
+ "index.js",
+ "server.js",
+ "types"
+ ],
+ "scripts": {
+ "start": "node bin.js",
+ "dev:client": "webpack --watch",
+ "dev:node": "webpack --watch --config webpack.node.config.js",
+ "build": "npm run build:client && npm run build:node",
+ "build:client": "rimraf ./build && cross-env NODE_ENV=production webpack",
+ "build:node": "rimraf ./build-node && cross-env NODE_ENV=production webpack --config webpack.node.config.js"
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "electron": "^21.0.1",
+ "express": "^4.17.1",
+ "ip": "^1.1.5",
+ "socket.io": "^4.4.0",
+ "socket.io-client": "^4.4.1",
+ "utf-8-validate": "^5.0.9"
+ },
+ "devDependencies": {
+ "@vue-devtools/app-backend-core": "^0.0.0",
+ "@vue-devtools/app-frontend": "^0.0.0",
+ "@vue-devtools/build-tools": "^0.0.0",
+ "@vue-devtools/shared-utils": "^0.0.0",
+ "rimraf": "^3.0.2",
+ "webpack": "^5.90.1",
+ "webpack-cli": "^5.1.4"
+ }
+}
\ No newline at end of file
diff --git a/vue-devtools/packages/shell-electron/server.js b/vue-devtools/packages/shell-electron/server.js
new file mode 100644
index 0000000000000000000000000000000000000000..15a729916b010cf43d253667f5e74d2842e42584
--- /dev/null
+++ b/vue-devtools/packages/shell-electron/server.js
@@ -0,0 +1,45 @@
+const path = require('node:path')
+const fs = require('node:fs')
+const { createServer } = require('node:http')
+const app = require('express')()
+const { Server } = require('socket.io')
+
+const port = process.env.PORT || 8098
+
+const httpServer = createServer(app)
+const io = new Server(httpServer, {
+ cors: {
+ origin: true,
+ },
+})
+
+app.get('/', (req, res) => {
+ const hookContent = fs.readFileSync(path.join(__dirname, '/build/hook.js'), 'utf8')
+ const backendContent = fs.readFileSync(path.join(__dirname, '/build/backend.js'), 'utf8')
+ res.send([hookContent, backendContent].join('\n'))
+})
+
+// Middleman
+io.on('connection', (socket) => {
+ // Disconnect any previously connected apps
+ socket.broadcast.emit('vue-devtools-disconnect-backend')
+
+ socket.on('vue-devtools-init', () => {
+ socket.broadcast.emit('vue-devtools-init')
+ })
+
+ socket.on('disconnect', (reason) => {
+ if (reason.indexOf('client')) {
+ socket.broadcast.emit('vue-devtools-disconnect-devtools')
+ }
+ })
+
+ socket.on('vue-message', (data) => {
+ socket.broadcast.emit('vue-message', data)
+ })
+})
+
+httpServer.listen(port, '0.0.0.0', () => {
+ // eslint-disable-next-line no-console
+ console.log(`listening on 0.0.0.0:${port}`)
+})
diff --git a/vue-devtools/packages/shell-electron/src/backend.js b/vue-devtools/packages/shell-electron/src/backend.js
new file mode 100644
index 0000000000000000000000000000000000000000..d4409fb0ed6d23b55f9dadd5a6c12f57c04a0223
--- /dev/null
+++ b/vue-devtools/packages/shell-electron/src/backend.js
@@ -0,0 +1,63 @@
+import io from 'socket.io-client'
+import { initBackend } from '@back'
+import { installToast } from '@back/toast'
+import { Bridge, chunk, target } from '@vue-devtools/shared-utils'
+
+const host = target.__VUE_DEVTOOLS_HOST__ || 'http://localhost'
+const port = target.__VUE_DEVTOOLS_PORT__ !== undefined ? target.__VUE_DEVTOOLS_PORT__ : 8098
+const fullHost = port ? `${host}:${port}` : host
+const createSocket = target.__VUE_DEVTOOLS_SOCKET__ || io
+const socket = createSocket(fullHost)
+const MAX_DATA_CHUNK = 2000
+
+function connectedMessage() {
+ if (target.__VUE_DEVTOOLS_TOAST__) {
+ target.__VUE_DEVTOOLS_TOAST__('Remote Devtools Connected', 'normal')
+ }
+}
+
+function disconnectedMessage() {
+ if (target.__VUE_DEVTOOLS_TOAST__) {
+ target.__VUE_DEVTOOLS_TOAST__('Remote Devtools Disconnected', 'error')
+ }
+}
+
+socket.on('connect', () => {
+ connectedMessage()
+ // eslint-disable-next-line ts/no-use-before-define
+ initBackend(bridge)
+ socket.emit('vue-devtools-init')
+})
+
+// Global disconnect handler. Fires in two cases:
+// - after calling above socket.disconnect()
+// - once devtools is closed (that's why we need socket.disconnect() here too, to prevent further polling)
+socket.on('disconnect', () => {
+ socket.disconnect()
+ disconnectedMessage()
+})
+
+// Disconnect socket once other client is connected
+socket.on('vue-devtools-disconnect-backend', () => {
+ socket.disconnect()
+})
+
+const bridge = new Bridge({
+ listen(fn) {
+ socket.on('vue-message', data => fn(data))
+ },
+ send(data) {
+ const chunks = chunk(data, MAX_DATA_CHUNK)
+
+ for (const chunk of chunks) {
+ socket.emit('vue-message', chunk)
+ }
+ },
+})
+
+bridge.on('shutdown', () => {
+ socket.disconnect()
+ disconnectedMessage()
+})
+
+installToast(target)
diff --git a/vue-devtools/packages/shell-electron/src/devtools.js b/vue-devtools/packages/shell-electron/src/devtools.js
new file mode 100644
index 0000000000000000000000000000000000000000..1fa3c57b611e04985ec1d6e3864fea30d8650d73
--- /dev/null
+++ b/vue-devtools/packages/shell-electron/src/devtools.js
@@ -0,0 +1,53 @@
+import io from 'socket.io-client'
+import { initDevTools } from '@front'
+import { Bridge } from '@vue-devtools/shared-utils'
+
+const port = window.process.env.PORT || 8098
+const socket = io(`http://localhost:${port}`)
+const $ = document.querySelector.bind(document)
+const $intro = $('#intro')
+
+let reload = null
+let introTimer
+
+socket.on('vue-devtools-disconnect-devtools', () => {
+ introTimer = setTimeout(() => {
+ $intro.classList.remove('hidden')
+ }, 2000)
+})
+
+socket.on('vue-devtools-init', () => {
+ clearTimeout(introTimer)
+ $intro.classList.add('hidden')
+
+ // Reset attached listeners
+ socket.off('vue-message')
+
+ // If new page is opened reload devtools
+ if (reload) {
+ return reload()
+ }
+
+ initDevTools({
+ connect(callback) {
+ const wall = {
+ listen(fn) {
+ socket.on('vue-message', data => fn(data))
+ },
+ send(data) {
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log('%cdevtools -> backend', 'color:#888;', data)
+ }
+ socket.emit('vue-message', data)
+ },
+ }
+ const bridge = new Bridge(wall)
+
+ callback(bridge)
+ },
+ onReload(fn) {
+ reload = fn
+ },
+ })
+})
diff --git a/vue-devtools/packages/shell-electron/src/hook.js b/vue-devtools/packages/shell-electron/src/hook.js
new file mode 100644
index 0000000000000000000000000000000000000000..f18c03adf157b008f10ef6ed25078c3435022dc8
--- /dev/null
+++ b/vue-devtools/packages/shell-electron/src/hook.js
@@ -0,0 +1,4 @@
+import { installHook } from '@back/hook'
+import { target } from '@vue-devtools/shared-utils'
+
+installHook(target)
diff --git a/vue-devtools/packages/shell-electron/types/index.d.ts b/vue-devtools/packages/shell-electron/types/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b30a2169c679d4e75c8cc3a1ede2bc82de40512
--- /dev/null
+++ b/vue-devtools/packages/shell-electron/types/index.d.ts
@@ -0,0 +1 @@
+export function connect(host?: string, port?: number | string): void
diff --git a/vue-devtools/packages/shell-electron/webpack.config.js b/vue-devtools/packages/shell-electron/webpack.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..d339bf403d3bc04038218de53ade13a107d68b5e
--- /dev/null
+++ b/vue-devtools/packages/shell-electron/webpack.config.js
@@ -0,0 +1,22 @@
+const path = require('node:path')
+const { createConfig } = require('@vue-devtools/build-tools')
+
+const target = {
+ chrome: 52,
+ firefox: 48,
+ safari: 9,
+ ie: 11,
+}
+
+module.exports = createConfig({
+ entry: {
+ devtools: './src/devtools.js',
+ backend: './src/backend.js',
+ hook: './src/hook.js',
+ },
+ output: {
+ path: path.join(__dirname, '/build'),
+ publicPath: '/build/',
+ filename: '[name].js',
+ },
+}, target)
diff --git a/vue-devtools/packages/shell-electron/webpack.node.config.js b/vue-devtools/packages/shell-electron/webpack.node.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..d50da2faba8175cb6fb90b57a110d0860948f269
--- /dev/null
+++ b/vue-devtools/packages/shell-electron/webpack.node.config.js
@@ -0,0 +1,28 @@
+const path = require('node:path')
+const { createConfig } = require('@vue-devtools/build-tools')
+
+const target = {
+ chrome: 52,
+ firefox: 48,
+ safari: 9,
+ ie: 11,
+}
+
+module.exports = createConfig({
+ target: 'node',
+ externals: {
+ // from https://socket.io/docs/v4/client-with-bundlers/
+ 'bufferutil': 'bufferutil',
+ 'utf-8-validate': 'utf-8-validate',
+ },
+ entry: {
+ devtools: './src/devtools.js',
+ backend: './src/backend.js',
+ hook: './src/hook.js',
+ },
+ output: {
+ path: path.join(__dirname, '/build-node'),
+ publicPath: '/build-node/',
+ filename: '[name].js',
+ },
+}, target)
diff --git a/vue-devtools/packages/shell-eruda/package.json b/vue-devtools/packages/shell-eruda/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..88b03d554a2742f4127f2f2c586e7f8b6a9e3631
--- /dev/null
+++ b/vue-devtools/packages/shell-eruda/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "@vue-devtools/shell-eruda",
+ "version": "0.0.0",
+ "scripts": {
+ "build": "rimraf ./build && cross-env NODE_ENV=production webpack --progress"
+ },
+ "dependencies": {
+ "@vue-devtools/app-backend-core": "^0.0.0",
+ "@vue-devtools/app-frontend": "^0.0.0",
+ "@vue-devtools/shared-utils": "^0.0.0"
+ },
+ "devDependencies": {
+ "@vue-devtools/build-tools": "^0.0.0",
+ "rimraf": "^3.0.2",
+ "webpack": "^5.90.1",
+ "webpack-cli": "^5.1.4"
+ }
+}
diff --git a/vue-devtools/packages/shell-eruda/src/devtools.js b/vue-devtools/packages/shell-eruda/src/devtools.js
new file mode 100644
index 0000000000000000000000000000000000000000..3d80827e04846ee3eda49ae5d1e3c59fb885131a
--- /dev/null
+++ b/vue-devtools/packages/shell-eruda/src/devtools.js
@@ -0,0 +1,22 @@
+import { initDevTools } from '@front'
+import { Bridge } from '@vue-devtools/shared-utils'
+
+const targetWindow = window.parent
+
+initDevTools({
+ connect(cb) {
+ cb(
+ new Bridge({
+ listen(fn) {
+ window.addEventListener('message', (evt) => {
+ fn(evt.data)
+ })
+ },
+ send(data) {
+ targetWindow.postMessage(data, '*')
+ },
+ })
+ )
+ },
+ onReload: () => {},
+})
diff --git a/vue-devtools/packages/shell-eruda/webpack.config.js b/vue-devtools/packages/shell-eruda/webpack.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..d2df6ef6ee5d16fc8910606a890281fc3380d977
--- /dev/null
+++ b/vue-devtools/packages/shell-eruda/webpack.config.js
@@ -0,0 +1,17 @@
+const path = require('node:path')
+const webpack = require('webpack')
+const { createConfig } = require('@vue-devtools/build-tools')
+
+module.exports = createConfig({
+ entry: './src/devtools.js',
+ output: {
+ path: path.join(__dirname, 'build'),
+ filename: 'devtools.js',
+ },
+ plugins: [
+ new webpack.optimize.LimitChunkCountPlugin({
+ maxChunks: 1,
+ }),
+ ],
+ devtool: process.env.NODE_ENV !== 'production' ? 'inline-source-map' : false,
+})
diff --git a/vue-devtools/packages/shell-firefox/.gitignore b/vue-devtools/packages/shell-firefox/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..b6560633a29cd21b672aa74a03863cb3996d9f5f
--- /dev/null
+++ b/vue-devtools/packages/shell-firefox/.gitignore
@@ -0,0 +1,3 @@
+icons/
+popups/
+*.html
diff --git a/vue-devtools/packages/shell-firefox/copy.sh b/vue-devtools/packages/shell-firefox/copy.sh
new file mode 100644
index 0000000000000000000000000000000000000000..15cba66b8ece0d0e8df28533cd2f98507f605eaf
--- /dev/null
+++ b/vue-devtools/packages/shell-firefox/copy.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+rm -rf icons
+
+cp -r ../shell-chrome/icons .
+cp -r ../shell-chrome/popups .
+cp ../shell-chrome/*.html .
diff --git a/vue-devtools/packages/shell-firefox/manifest.json b/vue-devtools/packages/shell-firefox/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..a449659f019b327fefe508f7a368785e5d3a34c9
--- /dev/null
+++ b/vue-devtools/packages/shell-firefox/manifest.json
@@ -0,0 +1,58 @@
+{
+ "name": "Vue.js devtools",
+ "version": "6.6.3",
+ "version_name": "6.6.3",
+ "description": "Browser DevTools extension for debugging Vue.js applications.",
+ "manifest_version": 2,
+ "icons": {
+ "16": "icons/16.png",
+ "48": "icons/48.png",
+ "128": "icons/128.png"
+ },
+ "browser_action": {
+ "default_icon": {
+ "16": "icons/16-gray.png",
+ "48": "icons/48-gray.png",
+ "128": "icons/128-gray.png"
+ },
+ "default_title": "Vue Devtools",
+ "default_popup": "popups/not-found.html"
+ },
+ "web_accessible_resources": [
+ "devtools.html",
+ "devtools-background.html",
+ "build/backend.js"
+ ],
+ "devtools_page": "devtools-background.html",
+ "background": {
+ "scripts": [
+ "build/background.js"
+ ],
+ "persistent": true
+ },
+ "permissions": [
+ "",
+ "storage"
+ ],
+ "content_scripts": [
+ {
+ "matches": [
+ ""
+ ],
+ "js": [
+ "build/hook.js"
+ ],
+ "run_at": "document_start"
+ },
+ {
+ "matches": [
+ ""
+ ],
+ "js": [
+ "build/detector.js"
+ ],
+ "run_at": "document_idle"
+ }
+ ],
+ "content_security_policy": "script-src 'self'; object-src 'self'"
+}
\ No newline at end of file
diff --git a/vue-devtools/packages/shell-firefox/package.json b/vue-devtools/packages/shell-firefox/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..d264786223088eca0575a297624f068572cd2988
--- /dev/null
+++ b/vue-devtools/packages/shell-firefox/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "@vue-devtools/shell-firefox",
+ "version": "0.0.0",
+ "scripts": {
+ "build": "rimraf ./build && ./copy.sh && cross-env NODE_ENV=production webpack --progress"
+ },
+ "dependencies": {
+ "@vue-devtools/app-backend-core": "^0.0.0",
+ "@vue-devtools/app-frontend": "^0.0.0",
+ "@vue-devtools/shared-utils": "^0.0.0"
+ },
+ "devDependencies": {
+ "@vue-devtools/build-tools": "^0.0.0",
+ "rimraf": "^3.0.2",
+ "webpack": "^5.35.1",
+ "webpack-cli": "^4.6.0"
+ }
+}
diff --git a/vue-devtools/packages/shell-firefox/src/backend.js b/vue-devtools/packages/shell-firefox/src/backend.js
new file mode 100644
index 0000000000000000000000000000000000000000..d0456e1dd0ddeaf8982d9d462eee33ba69e84cd0
--- /dev/null
+++ b/vue-devtools/packages/shell-firefox/src/backend.js
@@ -0,0 +1,55 @@
+// this is injected to the app page when the panel is activated.
+
+import { initBackend } from '@back'
+import { Bridge } from '@vue-devtools/shared-utils'
+
+window.addEventListener('message', handshake)
+
+function sendListening() {
+ window.postMessage({
+ source: 'vue-devtools-backend-injection',
+ payload: 'listening',
+ }, '*')
+}
+sendListening()
+
+function handshake(e) {
+ if (e.data.source === 'vue-devtools-proxy' && e.data.payload === 'init') {
+ window.removeEventListener('message', handshake)
+
+ let listeners = []
+ const bridge = new Bridge({
+ listen(fn) {
+ const listener = (evt) => {
+ if (evt.data.source === 'vue-devtools-proxy' && evt.data.payload) {
+ fn(evt.data.payload)
+ }
+ }
+ window.addEventListener('message', listener)
+ listeners.push(listener)
+ },
+ send(data) {
+ // if (process.env.NODE_ENV !== 'production') {
+ // console.log('[chrome] backend -> devtools', data)
+ // }
+ window.postMessage({
+ source: 'vue-devtools-backend',
+ payload: data,
+ }, '*')
+ },
+ })
+
+ bridge.on('shutdown', () => {
+ listeners.forEach((l) => {
+ window.removeEventListener('message', l)
+ })
+ listeners = []
+ window.addEventListener('message', handshake)
+ })
+
+ initBackend(bridge)
+ }
+ else {
+ sendListening()
+ }
+}
diff --git a/vue-devtools/packages/shell-firefox/src/background.js b/vue-devtools/packages/shell-firefox/src/background.js
new file mode 100644
index 0000000000000000000000000000000000000000..d4b7bab2ae71c1a77acf23e0885e488569b1f539
--- /dev/null
+++ b/vue-devtools/packages/shell-firefox/src/background.js
@@ -0,0 +1,125 @@
+// the background script runs all the time and serves as a central message
+// hub for each vue devtools (panel + proxy + backend) instance.
+
+const ports = {}
+
+chrome.runtime.onConnect.addListener((port) => {
+ let tab
+ let name
+ if (isNumeric(port.name)) {
+ tab = port.name
+ name = 'devtools'
+ installProxy(+port.name)
+ }
+ else {
+ tab = port.sender.tab.id
+ name = 'backend'
+ }
+
+ if (!ports[tab]) {
+ ports[tab] = {
+ devtools: null,
+ backend: null,
+ }
+ }
+ ports[tab][name] = port
+
+ if (ports[tab].devtools && ports[tab].backend) {
+ doublePipe(tab, ports[tab].devtools, ports[tab].backend)
+ }
+})
+
+function isNumeric(str) {
+ return `${+str}` === str
+}
+
+function installProxy(tabId) {
+ chrome.tabs.executeScript(tabId, {
+ file: '/build/proxy.js',
+ }, (res) => {
+ if (!res) {
+ ports[tabId].devtools.postMessage('proxy-fail')
+ }
+ else {
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log(`injected proxy to tab ${tabId}`)
+ }
+ }
+ })
+}
+
+function doublePipe(id, one, two) {
+ one.onMessage.addListener(lOne)
+ function lOne(message) {
+ if (message.event === 'log') {
+ // eslint-disable-next-line no-console
+ return console.log(`tab ${id}`, message.payload)
+ }
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log('%cdevtools -> backend', 'color:#888;', message)
+ }
+ two.postMessage(message)
+ }
+ two.onMessage.addListener(lTwo)
+ function lTwo(message) {
+ if (message.event === 'log') {
+ // eslint-disable-next-line no-console
+ return console.log(`tab ${id}`, message.payload)
+ }
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log('%cbackend -> devtools', 'color:#888;', message)
+ }
+ one.postMessage(message)
+ }
+ function shutdown() {
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log(`tab ${id} disconnected.`)
+ }
+ one.onMessage.removeListener(lOne)
+ two.onMessage.removeListener(lTwo)
+ one.disconnect()
+ two.disconnect()
+ ports[id] = null
+ }
+ one.onDisconnect.addListener(shutdown)
+ two.onDisconnect.addListener(shutdown)
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.log(`tab ${id} connected.`)
+ }
+}
+
+chrome.runtime.onMessage.addListener((req, sender) => {
+ if (sender.tab && req.vueDetected) {
+ const suffix = req.nuxtDetected ? '.nuxt' : ''
+
+ chrome.browserAction.setIcon({
+ tabId: sender.tab.id,
+ path: {
+ 16: `icons/16${suffix}.png`,
+ 48: `icons/48${suffix}.png`,
+ 128: `icons/128${suffix}.png`,
+ },
+ })
+ chrome.browserAction.setPopup({
+ tabId: sender.tab.id,
+ popup: req.devtoolsEnabled ? `popups/enabled${suffix}.html` : `popups/disabled${suffix}.html`,
+ })
+ }
+
+ if (req.action === 'vue-take-screenshot' && sender.envType === 'devtools_child') {
+ browser.tabs.captureVisibleTab({
+ format: 'png',
+ }).then((dataUrl) => {
+ browser.runtime.sendMessage({
+ action: 'vue-screenshot-result',
+ id: req.id,
+ dataUrl,
+ })
+ })
+ }
+})
diff --git a/vue-devtools/packages/shell-firefox/src/detector.js b/vue-devtools/packages/shell-firefox/src/detector.js
new file mode 100644
index 0000000000000000000000000000000000000000..f604854fe6f757b9f52e1aa26ad0c96cdf357e20
--- /dev/null
+++ b/vue-devtools/packages/shell-firefox/src/detector.js
@@ -0,0 +1,100 @@
+import { installToast } from '@back/toast'
+import { isFirefox } from '@vue-devtools/shared-utils'
+
+window.addEventListener('message', (e) => {
+ if (e.source === window && e.data.vueDetected) {
+ chrome.runtime.sendMessage(e.data)
+ }
+})
+
+function detect(win) {
+ let delay = 1000
+ let detectRemainingTries = 10
+
+ function runDetect() {
+ // Method 1: Check Nuxt
+ const nuxtDetected = !!(window.__NUXT__ || window.$nuxt)
+
+ if (nuxtDetected) {
+ let Vue
+
+ if (window.$nuxt) {
+ Vue = window.$nuxt.$root && window.$nuxt.$root.constructor
+ }
+
+ win.postMessage({
+ devtoolsEnabled: (/* Vue 2 */ Vue && Vue.config.devtools)
+ || (/* Vue 3.2.14+ */ window.__VUE_DEVTOOLS_GLOBAL_HOOK__ && window.__VUE_DEVTOOLS_GLOBAL_HOOK__.enabled),
+ vueDetected: true,
+ nuxtDetected: true,
+ }, '*')
+
+ return
+ }
+
+ // Method 2: Check Vue 3
+ const vueDetected = !!(window.__VUE__)
+ if (vueDetected) {
+ win.postMessage({
+ devtoolsEnabled: /* Vue 3.2.14+ */ window.__VUE_DEVTOOLS_GLOBAL_HOOK__ && window.__VUE_DEVTOOLS_GLOBAL_HOOK__.enabled,
+ vueDetected: true,
+ }, '*')
+
+ return
+ }
+
+ // Method 3: Scan all elements inside document
+ const all = document.querySelectorAll('*')
+ let el
+ for (let i = 0; i < all.length; i++) {
+ if (all[i].__vue__) {
+ el = all[i]
+ break
+ }
+ }
+ if (el) {
+ let Vue = Object.getPrototypeOf(el.__vue__).constructor
+ while (Vue.super) {
+ Vue = Vue.super
+ }
+ win.postMessage({
+ devtoolsEnabled: Vue.config.devtools,
+ vueDetected: true,
+ }, '*')
+ return
+ }
+
+ if (detectRemainingTries > 0) {
+ detectRemainingTries--
+ setTimeout(() => {
+ runDetect()
+ }, delay)
+ delay *= 5
+ }
+ }
+
+ setTimeout(() => {
+ runDetect()
+ }, 100)
+}
+
+// inject the hook
+if (document instanceof HTMLDocument) {
+ installScript(detect)
+ installScript(installToast)
+}
+
+function installScript(fn) {
+ const source = `;(${fn.toString()})(window)`
+
+ if (isFirefox) {
+ // eslint-disable-next-line no-eval
+ window.eval(source) // in Firefox, this evaluates on the content window
+ }
+ else {
+ const script = document.createElement('script')
+ script.textContent = source
+ document.documentElement.appendChild(script)
+ script.parentNode.removeChild(script)
+ }
+}
diff --git a/vue-devtools/packages/shell-firefox/src/devtools-background.js b/vue-devtools/packages/shell-firefox/src/devtools-background.js
new file mode 100644
index 0000000000000000000000000000000000000000..69aeb183b2878cdfa5b8b9328a5d5d638db3be5f
--- /dev/null
+++ b/vue-devtools/packages/shell-firefox/src/devtools-background.js
@@ -0,0 +1,48 @@
+// This is the devtools script, which is called when the user opens the
+// Chrome devtool on a page. We check to see if we global hook has detected
+// Vue presence on the page. If yes, create the Vue panel; otherwise poll
+// for 10 seconds.
+
+let created = false
+let checkCount = 0
+
+chrome.devtools.network.onNavigated.addListener(createPanelIfHasVue)
+const checkVueInterval = setInterval(createPanelIfHasVue, 1000)
+createPanelIfHasVue()
+
+function createPanelIfHasVue() {
+ if (created || checkCount++ > 10) {
+ clearInterval(checkVueInterval)
+ return
+ }
+ chrome.devtools.inspectedWindow.eval(
+ '!!(window.__VUE_DEVTOOLS_GLOBAL_HOOK__ && (window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue || window.__VUE_DEVTOOLS_GLOBAL_HOOK__.apps.length))',
+ (hasVue) => {
+ if (!hasVue || created) {
+ return
+ }
+ clearInterval(checkVueInterval)
+ created = true
+ chrome.devtools.panels.create(
+ 'Vue',
+ 'icons/128.png',
+ 'devtools.html',
+ (panel) => {
+ // panel loaded
+ panel.onShown.addListener(onPanelShown)
+ panel.onHidden.addListener(onPanelHidden)
+ },
+ )
+ },
+ )
+}
+
+// Manage panel visibility
+
+function onPanelShown() {
+ chrome.runtime.sendMessage('vue-panel-shown')
+}
+
+function onPanelHidden() {
+ chrome.runtime.sendMessage('vue-panel-hidden')
+}
diff --git a/vue-devtools/packages/shell-firefox/src/devtools.js b/vue-devtools/packages/shell-firefox/src/devtools.js
new file mode 100644
index 0000000000000000000000000000000000000000..21e2b2abc4b3e8152026ec1078237bf5e06f1d5a
--- /dev/null
+++ b/vue-devtools/packages/shell-firefox/src/devtools.js
@@ -0,0 +1,115 @@
+// this script is called when the VueDevtools panel is activated.
+
+import { initDevTools, setAppConnected } from '@front'
+import { Bridge, BridgeEvents } from '@vue-devtools/shared-utils'
+
+let disconnected = false
+let connectCount = 0
+let retryConnectTimer
+
+initDevTools({
+
+ /**
+ * Inject backend, connect to background, and send back the bridge.
+ *
+ * @param {Function} cb
+ */
+
+ connect(cb) {
+ // 1. inject backend code into page
+ injectScript(chrome.runtime.getURL('build/backend.js'), () => {
+ // 2. connect to background to setup proxy
+ let port
+
+ const onMessageHandlers = []
+
+ function connect() {
+ try {
+ clearTimeout(retryConnectTimer)
+ connectCount++
+ port = chrome.runtime.connect({
+ name: `${chrome.devtools.inspectedWindow.tabId}`,
+ })
+ disconnected = false
+ port.onDisconnect.addListener(() => {
+ disconnected = true
+ setAppConnected(false)
+
+ // Retry
+ retryConnectTimer = setTimeout(connect, 1000)
+ })
+
+ if (connectCount > 1) {
+ onMessageHandlers.forEach(fn => port.onMessage.addListener(fn))
+ }
+ }
+ catch (e) {
+ console.error(e)
+ disconnected = true
+ setAppConnected(false)
+
+ // Retry
+ retryConnectTimer = setTimeout(connect, 5000)
+ }
+ }
+ connect()
+
+ const bridge = new Bridge({
+ listen(fn) {
+ port.onMessage.addListener(fn)
+ onMessageHandlers.push(fn)
+ },
+ send(data) {
+ if (!disconnected) {
+ // if (process.env.NODE_ENV !== 'production') {
+ // console.log('[chrome] devtools -> backend', data)
+ // }
+ port.postMessage(data)
+ }
+ },
+ })
+
+ bridge.on(BridgeEvents.TO_FRONT_RECONNECTED, () => {
+ setAppConnected(true)
+ })
+
+ // 3. send a proxy API to the panel
+ cb(bridge)
+ })
+ },
+
+ /**
+ * Register a function to reload the devtools app.
+ *
+ * @param {Function} reloadFn
+ */
+
+ onReload(reloadFn) {
+ chrome.devtools.network.onNavigated.addListener(reloadFn)
+ },
+})
+
+/**
+ * Inject a globally evaluated script, in the same context with the actual
+ * user app.
+ *
+ * @param {string} scriptName
+ * @param {Function} cb
+ */
+
+function injectScript(scriptName, cb) {
+ const src = `
+ (function() {
+ var script = document.constructor.prototype.createElement.call(document, 'script');
+ script.src = "${scriptName}";
+ document.documentElement.appendChild(script);
+ script.parentNode.removeChild(script);
+ })()
+ `
+ chrome.devtools.inspectedWindow.eval(src, (res, err) => {
+ if (err) {
+ console.error(err)
+ }
+ cb()
+ })
+}
diff --git a/vue-devtools/packages/shell-firefox/src/hook.js b/vue-devtools/packages/shell-firefox/src/hook.js
new file mode 100644
index 0000000000000000000000000000000000000000..9d1e4d0303ec6c96233ec7d8b89273a4dda41700
--- /dev/null
+++ b/vue-devtools/packages/shell-firefox/src/hook.js
@@ -0,0 +1,19 @@
+// This script is injected into every page.
+import { installHook } from '@back/hook'
+import { isFirefox } from '@vue-devtools/shared-utils'
+
+// inject the hook
+if (document instanceof HTMLDocument) {
+ const source = `;(${installHook.toString()})(window)`
+
+ if (isFirefox) {
+ // eslint-disable-next-line no-eval
+ window.eval(source) // in Firefox, this evaluates on the content window
+ }
+ else {
+ const script = document.createElement('script')
+ script.textContent = source
+ document.documentElement.appendChild(script)
+ script.parentNode.removeChild(script)
+ }
+}
diff --git a/vue-devtools/packages/shell-firefox/src/proxy.js b/vue-devtools/packages/shell-firefox/src/proxy.js
new file mode 100644
index 0000000000000000000000000000000000000000..cb7e0e88abd90f2d66619e6725305b3808518ddf
--- /dev/null
+++ b/vue-devtools/packages/shell-firefox/src/proxy.js
@@ -0,0 +1,37 @@
+// This is a content-script that is injected only when the devtools are
+// activated. Because it is not injected using eval, it has full privilege
+// to the chrome runtime API. It serves as a proxy between the injected
+// backend and the Vue devtools panel.
+
+const port = chrome.runtime.connect({
+ name: 'content-script',
+})
+
+port.onMessage.addListener(sendMessageToBackend)
+window.addEventListener('message', sendMessageToDevtools)
+port.onDisconnect.addListener(handleDisconnect)
+
+sendMessageToBackend('init')
+
+function sendMessageToBackend(payload) {
+ window.postMessage({
+ source: 'vue-devtools-proxy',
+ payload,
+ }, '*')
+}
+
+function sendMessageToDevtools(e) {
+ if (e.data && e.data.source === 'vue-devtools-backend') {
+ port.postMessage(e.data.payload)
+ }
+ else if (e.data && e.data.source === 'vue-devtools-backend-injection') {
+ if (e.data.payload === 'listening') {
+ sendMessageToBackend('init')
+ }
+ }
+}
+
+function handleDisconnect() {
+ window.removeEventListener('message', sendMessageToDevtools)
+ sendMessageToBackend('shutdown')
+}
diff --git a/vue-devtools/packages/shell-firefox/webpack.config.js b/vue-devtools/packages/shell-firefox/webpack.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..eb111ac9701d9552672ef478fcecc0290eacba0d
--- /dev/null
+++ b/vue-devtools/packages/shell-firefox/webpack.config.js
@@ -0,0 +1,21 @@
+const path = require('node:path')
+const { createConfig } = require('@vue-devtools/build-tools')
+
+module.exports = createConfig({
+ entry: {
+ 'hook': './src/hook.js',
+ 'devtools': './src/devtools.js',
+ 'background': './src/background.js',
+ 'devtools-background': './src/devtools-background.js',
+ 'backend': './src/backend.js',
+ 'proxy': './src/proxy.js',
+ 'detector': './src/detector.js',
+ },
+ output: {
+ path: path.join(__dirname, 'build'),
+ filename: '[name].js',
+ },
+ devtool: process.env.NODE_ENV !== 'production'
+ ? 'inline-source-map'
+ : false,
+})
diff --git a/vue-devtools/packages/shell-host/package.json b/vue-devtools/packages/shell-host/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..1c59f56826e38a4df8005333da3163fcf368a51d
--- /dev/null
+++ b/vue-devtools/packages/shell-host/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "@vue-devtools/shell-host",
+ "version": "0.0.0",
+ "private": true,
+ "scripts": {
+ "dev": "cross-env TAILWIND_MODE=watch webpack serve"
+ },
+ "dependencies": {
+ "@vue-devtools/app-backend-core": "^0.0.0",
+ "@vue-devtools/app-frontend": "^0.0.0",
+ "@vue-devtools/shared-utils": "^0.0.0",
+ "vue": "^3.3.4"
+ },
+ "devDependencies": {
+ "cross-env": "^5.2.0",
+ "webpack": "^5.90.1",
+ "webpack-cli": "^5.1.4"
+ }
+}
diff --git a/vue-devtools/packages/shell-host/public/favicon.svg b/vue-devtools/packages/shell-host/public/favicon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4ee2e82507b0bf83f7b3843db2616d2eee8b330f
--- /dev/null
+++ b/vue-devtools/packages/shell-host/public/favicon.svg
@@ -0,0 +1,41 @@
+
+
diff --git a/vue-devtools/packages/shell-host/public/index.html b/vue-devtools/packages/shell-host/public/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..be7d7c2a193335ea7b536035cb1f42752cf94384
--- /dev/null
+++ b/vue-devtools/packages/shell-host/public/index.html
@@ -0,0 +1,39 @@
+
+
+
+
+ Plain Shell
+
+
+
+
+
+
+ Not Vue
+
+
+
+
diff --git a/vue-devtools/packages/shell-host/src/DevIframe.vue b/vue-devtools/packages/shell-host/src/DevIframe.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d3c892b016141c3373e114913a990219bdd23b77
--- /dev/null
+++ b/vue-devtools/packages/shell-host/src/DevIframe.vue
@@ -0,0 +1,228 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ You need to disable Chrome web security to allow manipulating an iframe on a different origin.
+
+
google-chrome --disable-web-security --disable-site-isolation-trials --user-data-dir="temp-chrome-data"
+
If the devtools have trouble connecting to the webpage, please put this snippet in the target app HTML before the main scripts:
+
+
+
+
+
+
+
+ Please
disable Chrome web security to allow manipulating an iframe on a different origin.
+
google-chrome --disable-web-security --disable-site-isolation-trials --user-data-dir="temp-chrome-data"
+
+
+
diff --git a/vue-devtools/packages/shell-host/src/backend.js b/vue-devtools/packages/shell-host/src/backend.js
new file mode 100644
index 0000000000000000000000000000000000000000..0ad207fd45719060ac19efed69aba22f2c9cfdb8
--- /dev/null
+++ b/vue-devtools/packages/shell-host/src/backend.js
@@ -0,0 +1,16 @@
+import { initBackend } from '@back'
+import { Bridge } from '@vue-devtools/shared-utils'
+
+const bridge = new Bridge({
+ listen(fn) {
+ window.addEventListener('message', evt => fn(evt.data))
+ },
+ send(data) {
+ if (process.env.NODE_ENV !== 'production') {
+ console.log('%cbackend -> devtools', 'color:#888;', data)
+ }
+ window.parent.postMessage(data, '*')
+ },
+})
+
+initBackend(bridge)
diff --git a/vue-devtools/packages/shell-host/src/devtools.js b/vue-devtools/packages/shell-host/src/devtools.js
new file mode 100644
index 0000000000000000000000000000000000000000..6edba4485ef9b9f3299a13c22cd1857cb049933b
--- /dev/null
+++ b/vue-devtools/packages/shell-host/src/devtools.js
@@ -0,0 +1,7 @@
+import { createApp } from 'vue'
+import { setupPlugins } from '@front/plugins'
+import DevIframe from './DevIframe.vue'
+
+const app = createApp(DevIframe)
+setupPlugins(app)
+app.mount('#iframe-target')
diff --git a/vue-devtools/packages/shell-host/src/hook.js b/vue-devtools/packages/shell-host/src/hook.js
new file mode 100644
index 0000000000000000000000000000000000000000..7549d0f1680ea57e63532157a23d3551096b1079
--- /dev/null
+++ b/vue-devtools/packages/shell-host/src/hook.js
@@ -0,0 +1,3 @@
+import { installHook } from '@back/hook'
+
+installHook(window)
diff --git a/vue-devtools/packages/shell-host/webpack.config.js b/vue-devtools/packages/shell-host/webpack.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..4de27d11c289ad711345d84253ca6efbf0727dd2
--- /dev/null
+++ b/vue-devtools/packages/shell-host/webpack.config.js
@@ -0,0 +1,20 @@
+const path = require('node:path')
+const { createConfig } = require('@vue-devtools/build-tools')
+const openInEditor = require('launch-editor-middleware')
+
+module.exports = createConfig({
+ entry: {
+ devtools: './src/devtools.js',
+ },
+ output: {
+ path: path.join(__dirname, '/build'),
+ publicPath: '/build/',
+ filename: '[name].js',
+ },
+ devServer: {
+ port: 8091,
+ onBeforeSetupMiddleware({ app }) {
+ app.use('/__open-in-editor', openInEditor())
+ },
+ },
+})
diff --git a/vue-devtools/postcss.config.js b/vue-devtools/postcss.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..32ac6213a121c654ffbd6a9df9c38836955d89d1
--- /dev/null
+++ b/vue-devtools/postcss.config.js
@@ -0,0 +1,9 @@
+const path = require('node:path')
+
+module.exports = {
+ plugins: [
+ require('autoprefixer'),
+ require('tailwindcss')(path.resolve(__dirname, './tailwind.config.js')),
+ require('postcss-nested'),
+ ],
+}
diff --git a/vue-devtools/release.js b/vue-devtools/release.js
new file mode 100644
index 0000000000000000000000000000000000000000..6b1c3b71356d669f43f4c5e973bbc79b74cc918b
--- /dev/null
+++ b/vue-devtools/release.js
@@ -0,0 +1,82 @@
+const fs = require('node:fs')
+const inquirer = require('inquirer')
+const semver = require('semver')
+const pkg = require('./package.json')
+const manifest = require('./packages/shell-chrome/manifest.json')
+const manifestFirefox = require('./packages/shell-firefox/manifest.json')
+
+const IS_CI = !!(process.env.CIRCLECI || process.env.GITHUB_ACTIONS)
+
+const curVersion = pkg.version
+
+;(async () => {
+ const { newVersion } = IS_CI
+ ? { newVersion: curVersion }
+ : await inquirer.prompt([{
+ type: 'input',
+ name: 'newVersion',
+ message: `Please provide a version (current: ${curVersion}):`,
+ }])
+
+ if (!semver.valid(newVersion)) {
+ console.error(`Invalid version: ${newVersion}`)
+ process.exit(1)
+ }
+
+ if (semver.lt(newVersion, curVersion)) {
+ console.error(`New version (${newVersion}) cannot be lower than current version (${curVersion}).`)
+ process.exit(1)
+ }
+
+ const { yes } = IS_CI
+ ? { yes: true }
+ : await inquirer.prompt([{
+ name: 'yes',
+ message: `Release ${newVersion}?`,
+ type: 'confirm',
+ }])
+
+ if (yes) {
+ const isBeta = newVersion.includes('beta')
+ pkg.version = newVersion
+ if (isBeta) {
+ const [, baseVersion, betaVersion] = /(.*)-beta\.(\w+)/.exec(newVersion)
+ manifest.version = `${baseVersion}.${betaVersion}`
+ manifest.version_name = `${baseVersion} beta ${betaVersion}`
+ applyIcons(manifest, '-beta')
+ }
+ else {
+ manifest.version = newVersion
+ manifest.version_name = newVersion
+ applyIcons(manifest)
+ }
+
+ manifestFirefox.version = manifest.version
+ manifestFirefox.version_name = manifest.version_name
+
+ fs.writeFileSync('./package.json', JSON.stringify(pkg, null, 2))
+ {
+ // Electron package
+ const pkg = require('./packages/shell-electron/package.json')
+ pkg.version = newVersion
+ fs.writeFileSync('./packages/shell-electron/package.json', JSON.stringify(pkg, null, 2))
+ }
+ {
+ // API package
+ const pkg = require('./packages/api/package.json')
+ pkg.version = newVersion
+ fs.writeFileSync('./packages/api/package.json', JSON.stringify(pkg, null, 2))
+ }
+ fs.writeFileSync('./packages/shell-chrome/manifest.json', JSON.stringify(manifest, null, 2))
+ fs.writeFileSync('./packages/shell-firefox/manifest.json', JSON.stringify(manifestFirefox, null, 2))
+ }
+ else {
+ process.exit(1)
+ }
+})()
+
+function applyIcons(manifest, suffix = '') {
+ [16, 48, 128].forEach((size) => {
+ manifest.icons[size] = `icons/${size}${suffix}.png`
+ })
+}
diff --git a/vue-devtools/sign-firefox.js b/vue-devtools/sign-firefox.js
new file mode 100644
index 0000000000000000000000000000000000000000..1af379266f78ee2df6fc8174accf60239989a62b
--- /dev/null
+++ b/vue-devtools/sign-firefox.js
@@ -0,0 +1,43 @@
+/* eslint-disable no-console */
+
+const path = require('node:path')
+const fs = require('node:fs')
+const execa = require('execa')
+
+const credFile = path.resolve(__dirname, '.amo.env.json')
+
+if (!fs.existsSync(credFile)) {
+ fs.writeFileSync(credFile, JSON.stringify({
+ apiKey: '',
+ apiSecret: '',
+ }, null, 2), { encoding: 'utf8' })
+ console.log('Please provide Mozilla API credentials in .amo.env.json\nhttps://addons.mozilla.org/developers/addon/api/key/')
+ process.exit(1)
+}
+
+const creds = JSON.parse(fs.readFileSync(credFile, {
+ encoding: 'utf8',
+}))
+
+const child = execa('web-ext', [
+ 'sign',
+ '--api-key',
+ creds.apiKey,
+ '--api-secret',
+ creds.apiSecret,
+ '-s',
+ 'packages/shell-chrome',
+ '-a',
+ 'dist',
+ '-i',
+ 'src',
+ '--id',
+ '{c087fa6e-b59f-475d-b08d-f03fef34fa7f}',
+], {
+ shell: true,
+ stdio: ['inherit', 'inherit', 'inherit'],
+})
+
+child.on('exit', (code) => {
+ process.exit(code)
+})
diff --git a/vue-devtools/tailwind.config.js b/vue-devtools/tailwind.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..04d3f26e78ba6a5947dad43ab7a3839db0befb15
--- /dev/null
+++ b/vue-devtools/tailwind.config.js
@@ -0,0 +1,115 @@
+const path = require('node:path')
+
+module.exports = {
+ theme: {
+ extend: {
+ colors: {
+ green: {
+ 50: '#ecf8f7',
+ 100: '#d3f7ef',
+ 200: '#a5f2db',
+ 300: '#66e9c2',
+ 400: '#20d99b',
+ 500: '#42B983',
+ 600: '#09ab56',
+ 700: '#0f8c4a',
+ 800: '#126e41',
+ 900: '#115937',
+ },
+ purple: {
+ 50: '#f3f3fa',
+ 100: '#ece3fa',
+ 200: '#ddc3f9',
+ 300: '#cea3f9',
+ 400: '#c378f9',
+ 500: '#a44cf6',
+ 600: '#a331f7',
+ 700: '#8128e8',
+ 800: '#6523c4',
+ 900: '#521fa0',
+ },
+ gray: {
+ 50: '#fafafa',
+ 100: '#f5f5f5',
+ 200: '#e5e5e5',
+ 300: '#d4d4d4',
+ 400: '#a3a3a3',
+ 500: '#737373',
+ 600: '#525252',
+ 700: '#404040',
+ 800: '#262626',
+ 900: '#171717',
+ 950: '#0a0a0a',
+ },
+ bluegray: {
+ 50: '#f3f9fb',
+ 100: '#e4f4f9',
+ 200: '#c5e7f4',
+ 300: '#9cd5f0',
+ 400: '#89a9c9',
+ 500: '#328de3',
+ 600: '#266ad2',
+ 700: '#2653ae',
+ 800: '#224082',
+ 900: '#1d3564',
+ },
+ black: '#0b1015',
+ },
+ cursor: {
+ 'ew-resize': 'ew-resize',
+ 'ns-resize': 'ns-resize',
+ },
+ zIndex: {
+ 60: 60,
+ 70: 70,
+ 80: 80,
+ 90: 90,
+ 100: 100,
+ },
+ fontFamily: {
+ mono: '\'Roboto Mono\', Menlo, Consolas, monospace',
+ },
+ fontSize: {
+ '2xs': '.65rem',
+ '3xs': '.6rem',
+ },
+ spacing: {
+ 0.5: '0.125rem',
+ 72: '18rem',
+ 80: '20rem',
+ 96: '24rem',
+ },
+ maxWidth: theme => ({
+ ...theme('width'),
+ }),
+ minWidth: theme => ({
+ ...theme('width'),
+ }),
+ maxHeight: theme => ({
+ ...theme('width'),
+ }),
+ minHeight: theme => ({
+ ...theme('width'),
+ }),
+ },
+ },
+ variants: {
+ backgroundColor: ['hover', 'group-hover', 'dark'],
+ backgroundOpacity: ['hover', 'group-hover', 'dark'],
+ textColor: ['hover', 'group-hover', 'dark'],
+ visibility: ['group-hover'],
+ },
+ darkMode: 'class',
+ mode: 'jit',
+ purge: {
+ content: [
+ path.resolve(__dirname, './packages/app-frontend/src/**/*.{js,jsx,ts,tsx,vue}'),
+ path.resolve(__dirname, './packages/app-backend-core/src/**/*.{js,jsx,ts,tsx,vue}'),
+ path.resolve(__dirname, './packages/app-backend-vue1/src/**/*.{js,jsx,ts,tsx,vue}'),
+ path.resolve(__dirname, './packages/app-backend-vue2/src/**/*.{js,jsx,ts,tsx,vue}'),
+ path.resolve(__dirname, './packages/app-backend-vue3/src/**/*.{js,jsx,ts,tsx,vue}'),
+ path.resolve(__dirname, './packages/shared-utils/src/**/*.{js,jsx,ts,tsx,vue}'),
+ path.resolve(__dirname, './packages/shell-host/src/**/*.{js,jsx,ts,tsx,vue}'),
+ ],
+ },
+}
diff --git a/vue-devtools/tsconfig.json b/vue-devtools/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..b8b6dead6f74e10acd1322d94f8cf3c521fbcf92
--- /dev/null
+++ b/vue-devtools/tsconfig.json
@@ -0,0 +1,40 @@
+{
+ "compilerOptions": {
+ "target": "ES2019",
+ "jsx": "preserve",
+ "baseUrl": ".",
+ "moduleResolution": "node",
+ "paths": {
+ "@back/*": [
+ "packages/app-backend-core/src/*"
+ ],
+ "@front/*": [
+ "packages/app-frontend/src/*"
+ ]
+ },
+ "resolveJsonModule": true,
+ "types": [
+ "chrome",
+ "node",
+ "webpack-env"
+ ],
+ "allowJs": true,
+ "strictBindCallApply": true,
+ "strictFunctionTypes": true,
+ "alwaysStrict": true,
+ // Strict
+ "noImplicitAny": false,
+ "noImplicitThis": true,
+ "outDir": "lib",
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true
+ },
+ "include": [
+ "packages/app-frontend/src/**/*",
+ "packages/shared-utils/src/**/*"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/vue-devtools/vue1-test.html b/vue-devtools/vue1-test.html
new file mode 100644
index 0000000000000000000000000000000000000000..87cc8f92ff1b2ea9d31a9ed3d48dd8510b476847
--- /dev/null
+++ b/vue-devtools/vue1-test.html
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/vue-devtools/yarn.lock b/vue-devtools/yarn.lock
new file mode 100644
index 0000000000000000000000000000000000000000..1027b5826a62afd6d700119af67c4eb470d6ca25
--- /dev/null
+++ b/vue-devtools/yarn.lock
@@ -0,0 +1,12756 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@aashutoshrathi/word-wrap@^1.2.3":
+ version "1.2.6"
+ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf"
+ integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==
+
+"@akryum/md-icons-svg@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@akryum/md-icons-svg/-/md-icons-svg-1.0.1.tgz#bd4b88a70549e3e43acef342e1414c786544f72e"
+ integrity sha512-77uYSiIEKLlB4/lmVlOfcbypkD098rFC1jLaoIG8kQZARZD2HG7WhJNzwgGFFFuSO6WFSmAg/YtBJytHaMLRlQ==
+
+"@algolia/autocomplete-core@1.7.1":
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.7.1.tgz#025538b8a9564a9f3dd5bcf8a236d6951c76c7d1"
+ integrity sha512-eiZw+fxMzNQn01S8dA/hcCpoWCOCwcIIEUtHHdzN5TGB3IpzLbuhqFeTfh2OUhhgkE8Uo17+wH+QJ/wYyQmmzg==
+ dependencies:
+ "@algolia/autocomplete-shared" "1.7.1"
+
+"@algolia/autocomplete-preset-algolia@1.7.1":
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.7.1.tgz#7dadc5607097766478014ae2e9e1c9c4b3f957c8"
+ integrity sha512-pJwmIxeJCymU1M6cGujnaIYcY3QPOVYZOXhFkWVM7IxKzy272BwCvMFMyc5NpG/QmiObBxjo7myd060OeTNJXg==
+ dependencies:
+ "@algolia/autocomplete-shared" "1.7.1"
+
+"@algolia/autocomplete-shared@1.7.1":
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.1.tgz#95c3a0b4b78858fed730cf9c755b7d1cd0c82c74"
+ integrity sha512-eTmGVqY3GeyBTT8IWiB2K5EuURAqhnumfktAEoHxfDY2o7vg2rSnO16ZtIG0fMgt3py28Vwgq42/bVEuaQV7pg==
+
+"@algolia/cache-browser-local-storage@4.14.2":
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.14.2.tgz#d5b1b90130ca87c6321de876e167df9ec6524936"
+ integrity sha512-FRweBkK/ywO+GKYfAWbrepewQsPTIEirhi1BdykX9mxvBPtGNKccYAxvGdDCumU1jL4r3cayio4psfzKMejBlA==
+ dependencies:
+ "@algolia/cache-common" "4.14.2"
+
+"@algolia/cache-common@4.14.2":
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.14.2.tgz#b946b6103c922f0c06006fb6929163ed2c67d598"
+ integrity sha512-SbvAlG9VqNanCErr44q6lEKD2qoK4XtFNx9Qn8FK26ePCI8I9yU7pYB+eM/cZdS9SzQCRJBbHUumVr4bsQ4uxg==
+
+"@algolia/cache-in-memory@4.14.2":
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.14.2.tgz#88e4a21474f9ac05331c2fa3ceb929684a395a24"
+ integrity sha512-HrOukWoop9XB/VFojPv1R5SVXowgI56T9pmezd/djh2JnVN/vXswhXV51RKy4nCpqxyHt/aGFSq2qkDvj6KiuQ==
+ dependencies:
+ "@algolia/cache-common" "4.14.2"
+
+"@algolia/client-account@4.14.2":
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.14.2.tgz#b76ac1ba9ea71e8c3f77a1805b48350dc0728a16"
+ integrity sha512-WHtriQqGyibbb/Rx71YY43T0cXqyelEU0lB2QMBRXvD2X0iyeGl4qMxocgEIcbHyK7uqE7hKgjT8aBrHqhgc1w==
+ dependencies:
+ "@algolia/client-common" "4.14.2"
+ "@algolia/client-search" "4.14.2"
+ "@algolia/transporter" "4.14.2"
+
+"@algolia/client-analytics@4.14.2":
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.14.2.tgz#ca04dcaf9a78ee5c92c5cb5e9c74cf031eb2f1fb"
+ integrity sha512-yBvBv2mw+HX5a+aeR0dkvUbFZsiC4FKSnfqk9rrfX+QrlNOKEhCG0tJzjiOggRW4EcNqRmaTULIYvIzQVL2KYQ==
+ dependencies:
+ "@algolia/client-common" "4.14.2"
+ "@algolia/client-search" "4.14.2"
+ "@algolia/requester-common" "4.14.2"
+ "@algolia/transporter" "4.14.2"
+
+"@algolia/client-common@4.14.2":
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.14.2.tgz#e1324e167ffa8af60f3e8bcd122110fd0bfd1300"
+ integrity sha512-43o4fslNLcktgtDMVaT5XwlzsDPzlqvqesRi4MjQz2x4/Sxm7zYg5LRYFol1BIhG6EwxKvSUq8HcC/KxJu3J0Q==
+ dependencies:
+ "@algolia/requester-common" "4.14.2"
+ "@algolia/transporter" "4.14.2"
+
+"@algolia/client-personalization@4.14.2":
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.14.2.tgz#656bbb6157a3dd1a4be7de65e457fda136c404ec"
+ integrity sha512-ACCoLi0cL8CBZ1W/2juehSltrw2iqsQBnfiu/Rbl9W2yE6o2ZUb97+sqN/jBqYNQBS+o0ekTMKNkQjHHAcEXNw==
+ dependencies:
+ "@algolia/client-common" "4.14.2"
+ "@algolia/requester-common" "4.14.2"
+ "@algolia/transporter" "4.14.2"
+
+"@algolia/client-search@4.14.2":
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.14.2.tgz#357bdb7e640163f0e33bad231dfcc21f67dc2e92"
+ integrity sha512-L5zScdOmcZ6NGiVbLKTvP02UbxZ0njd5Vq9nJAmPFtjffUSOGEp11BmD2oMJ5QvARgx2XbX4KzTTNS5ECYIMWw==
+ dependencies:
+ "@algolia/client-common" "4.14.2"
+ "@algolia/requester-common" "4.14.2"
+ "@algolia/transporter" "4.14.2"
+
+"@algolia/logger-common@4.14.2":
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.14.2.tgz#b74b3a92431f92665519d95942c246793ec390ee"
+ integrity sha512-/JGlYvdV++IcMHBnVFsqEisTiOeEr6cUJtpjz8zc0A9c31JrtLm318Njc72p14Pnkw3A/5lHHh+QxpJ6WFTmsA==
+
+"@algolia/logger-console@4.14.2":
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.14.2.tgz#ec49cb47408f5811d4792598683923a800abce7b"
+ integrity sha512-8S2PlpdshbkwlLCSAB5f8c91xyc84VM9Ar9EdfE9UmX+NrKNYnWR1maXXVDQQoto07G1Ol/tYFnFVhUZq0xV/g==
+ dependencies:
+ "@algolia/logger-common" "4.14.2"
+
+"@algolia/requester-browser-xhr@4.14.2":
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.14.2.tgz#a2cd4d9d8d90d53109cc7f3682dc6ebf20f798f2"
+ integrity sha512-CEh//xYz/WfxHFh7pcMjQNWgpl4wFB85lUMRyVwaDPibNzQRVcV33YS+63fShFWc2+42YEipFGH2iPzlpszmDw==
+ dependencies:
+ "@algolia/requester-common" "4.14.2"
+
+"@algolia/requester-common@4.14.2":
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.14.2.tgz#bc4e9e5ee16c953c0ecacbfb334a33c30c28b1a1"
+ integrity sha512-73YQsBOKa5fvVV3My7iZHu1sUqmjjfs9TteFWwPwDmnad7T0VTCopttcsM3OjLxZFtBnX61Xxl2T2gmG2O4ehg==
+
+"@algolia/requester-node-http@4.14.2":
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.14.2.tgz#7c1223a1785decaab1def64c83dade6bea45e115"
+ integrity sha512-oDbb02kd1o5GTEld4pETlPZLY0e+gOSWjWMJHWTgDXbv9rm/o2cF7japO6Vj1ENnrqWvLBmW1OzV9g6FUFhFXg==
+ dependencies:
+ "@algolia/requester-common" "4.14.2"
+
+"@algolia/transporter@4.14.2":
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.14.2.tgz#77c069047fb1a4359ee6a51f51829508e44a1e3d"
+ integrity sha512-t89dfQb2T9MFQHidjHcfhh6iGMNwvuKUvojAj+JsrHAGbuSy7yE4BylhLX6R0Q1xYRoC4Vvv+O5qIw/LdnQfsQ==
+ dependencies:
+ "@algolia/cache-common" "4.14.2"
+ "@algolia/logger-common" "4.14.2"
+ "@algolia/requester-common" "4.14.2"
+
+"@ampproject/remapping@^2.1.0":
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d"
+ integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.1.0"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@antfu/eslint-config@^2.19.1":
+ version "2.19.1"
+ resolved "https://registry.yarnpkg.com/@antfu/eslint-config/-/eslint-config-2.19.1.tgz#175e2e2644655a5d3f2f6d8d0f516c92d28bd92f"
+ integrity sha512-gtiyWxoBnk39Vgf23xJiSQrq3esEGYesv7Q4IZXEJJaYSpyiJWHMYxlC6dFr4V9tAczDa7bZjR9E6XWEiU7VEA==
+ dependencies:
+ "@antfu/install-pkg" "^0.3.3"
+ "@clack/prompts" "^0.7.0"
+ "@stylistic/eslint-plugin" "^2.1.0"
+ "@typescript-eslint/eslint-plugin" "^7.11.0"
+ "@typescript-eslint/parser" "^7.11.0"
+ eslint-config-flat-gitignore "^0.1.5"
+ eslint-flat-config-utils "^0.2.5"
+ eslint-merge-processors "^0.1.0"
+ eslint-plugin-antfu "^2.3.2"
+ eslint-plugin-command "^0.2.3"
+ eslint-plugin-eslint-comments "^3.2.0"
+ eslint-plugin-import-x "^0.5.1"
+ eslint-plugin-jsdoc "^48.2.6"
+ eslint-plugin-jsonc "^2.16.0"
+ eslint-plugin-markdown "^5.0.0"
+ eslint-plugin-n "^17.7.0"
+ eslint-plugin-no-only-tests "^3.1.0"
+ eslint-plugin-perfectionist "^2.10.0"
+ eslint-plugin-regexp "^2.6.0"
+ eslint-plugin-toml "^0.11.0"
+ eslint-plugin-unicorn "^53.0.0"
+ eslint-plugin-unused-imports "^3.2.0"
+ eslint-plugin-vitest "^0.5.4"
+ eslint-plugin-vue "^9.26.0"
+ eslint-plugin-yml "^1.14.0"
+ eslint-processor-vue-blocks "^0.1.2"
+ globals "^15.3.0"
+ jsonc-eslint-parser "^2.4.0"
+ local-pkg "^0.5.0"
+ parse-gitignore "^2.0.0"
+ picocolors "^1.0.1"
+ toml-eslint-parser "^0.9.3"
+ vue-eslint-parser "^9.4.2"
+ yaml-eslint-parser "^1.2.3"
+ yargs "^17.7.2"
+
+"@antfu/install-pkg@^0.3.3":
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/@antfu/install-pkg/-/install-pkg-0.3.3.tgz#34c3837132157e6ca23fe9587d1e174b0f33dc1a"
+ integrity sha512-nHHsk3NXQ6xkCfiRRC8Nfrg8pU5kkr3P3Y9s9dKqiuRmBD0Yap7fymNDjGFKeWhZQHqqbCS5CfeMy9wtExM24w==
+ dependencies:
+ "@jsdevtools/ez-spawn" "^3.0.4"
+
+"@antfu/utils@^0.7.8":
+ version "0.7.8"
+ resolved "https://registry.yarnpkg.com/@antfu/utils/-/utils-0.7.8.tgz#86cb0974bcab7e64e29b57d6d9021102307257de"
+ integrity sha512-rWQkqXRESdjXtc+7NRfK9lASQjpXJu1ayp7qi1d23zZorY+wBHVLHHoVcMsEnkqEBWTFqbztO7/QdJFzyEcLTg==
+
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a"
+ integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==
+ dependencies:
+ "@babel/highlight" "^7.18.6"
+
+"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8", "@babel/compat-data@^7.19.1":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.1.tgz#72d647b4ff6a4f82878d184613353af1dd0290f9"
+ integrity sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg==
+
+"@babel/core@^7.16.0":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.1.tgz#c8fa615c5e88e272564ace3d42fbc8b17bfeb22b"
+ integrity sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw==
+ dependencies:
+ "@ampproject/remapping" "^2.1.0"
+ "@babel/code-frame" "^7.18.6"
+ "@babel/generator" "^7.19.0"
+ "@babel/helper-compilation-targets" "^7.19.1"
+ "@babel/helper-module-transforms" "^7.19.0"
+ "@babel/helpers" "^7.19.0"
+ "@babel/parser" "^7.19.1"
+ "@babel/template" "^7.18.10"
+ "@babel/traverse" "^7.19.1"
+ "@babel/types" "^7.19.0"
+ convert-source-map "^1.7.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.2"
+ json5 "^2.2.1"
+ semver "^6.3.0"
+
+"@babel/generator@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.0.tgz#785596c06425e59334df2ccee63ab166b738419a"
+ integrity sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==
+ dependencies:
+ "@babel/types" "^7.19.0"
+ "@jridgewell/gen-mapping" "^0.3.2"
+ jsesc "^2.5.1"
+
+"@babel/helper-annotate-as-pure@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb"
+ integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==
+ dependencies:
+ "@babel/types" "^7.18.6"
+
+"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb"
+ integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==
+ dependencies:
+ "@babel/helper-explode-assignable-expression" "^7.18.6"
+ "@babel/types" "^7.18.9"
+
+"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.19.0", "@babel/helper-compilation-targets@^7.19.1":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz#7f630911d83b408b76fe584831c98e5395d7a17c"
+ integrity sha512-LlLkkqhCMyz2lkQPvJNdIYU7O5YjWRgC2R4omjCTpZd8u8KMQzZvX4qce+/BluN1rcQiV7BoGUpmQ0LeHerbhg==
+ dependencies:
+ "@babel/compat-data" "^7.19.1"
+ "@babel/helper-validator-option" "^7.18.6"
+ browserslist "^4.21.3"
+ semver "^6.3.0"
+
+"@babel/helper-create-class-features-plugin@^7.18.6":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz#bfd6904620df4e46470bae4850d66be1054c404b"
+ integrity sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.18.6"
+ "@babel/helper-environment-visitor" "^7.18.9"
+ "@babel/helper-function-name" "^7.19.0"
+ "@babel/helper-member-expression-to-functions" "^7.18.9"
+ "@babel/helper-optimise-call-expression" "^7.18.6"
+ "@babel/helper-replace-supers" "^7.18.9"
+ "@babel/helper-split-export-declaration" "^7.18.6"
+
+"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b"
+ integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.18.6"
+ regexpu-core "^5.1.0"
+
+"@babel/helper-define-polyfill-provider@^0.3.3":
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a"
+ integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==
+ dependencies:
+ "@babel/helper-compilation-targets" "^7.17.7"
+ "@babel/helper-plugin-utils" "^7.16.7"
+ debug "^4.1.1"
+ lodash.debounce "^4.0.8"
+ resolve "^1.14.2"
+ semver "^6.1.2"
+
+"@babel/helper-environment-visitor@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be"
+ integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==
+
+"@babel/helper-explode-assignable-expression@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096"
+ integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==
+ dependencies:
+ "@babel/types" "^7.18.6"
+
+"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c"
+ integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==
+ dependencies:
+ "@babel/template" "^7.18.10"
+ "@babel/types" "^7.19.0"
+
+"@babel/helper-hoist-variables@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678"
+ integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==
+ dependencies:
+ "@babel/types" "^7.18.6"
+
+"@babel/helper-member-expression-to-functions@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815"
+ integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==
+ dependencies:
+ "@babel/types" "^7.18.9"
+
+"@babel/helper-module-imports@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e"
+ integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==
+ dependencies:
+ "@babel/types" "^7.18.6"
+
+"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz#309b230f04e22c58c6a2c0c0c7e50b216d350c30"
+ integrity sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.18.9"
+ "@babel/helper-module-imports" "^7.18.6"
+ "@babel/helper-simple-access" "^7.18.6"
+ "@babel/helper-split-export-declaration" "^7.18.6"
+ "@babel/helper-validator-identifier" "^7.18.6"
+ "@babel/template" "^7.18.10"
+ "@babel/traverse" "^7.19.0"
+ "@babel/types" "^7.19.0"
+
+"@babel/helper-optimise-call-expression@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe"
+ integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==
+ dependencies:
+ "@babel/types" "^7.18.6"
+
+"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf"
+ integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==
+
+"@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519"
+ integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.18.6"
+ "@babel/helper-environment-visitor" "^7.18.9"
+ "@babel/helper-wrap-function" "^7.18.9"
+ "@babel/types" "^7.18.9"
+
+"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.18.9":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78"
+ integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.18.9"
+ "@babel/helper-member-expression-to-functions" "^7.18.9"
+ "@babel/helper-optimise-call-expression" "^7.18.6"
+ "@babel/traverse" "^7.19.1"
+ "@babel/types" "^7.19.0"
+
+"@babel/helper-simple-access@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea"
+ integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==
+ dependencies:
+ "@babel/types" "^7.18.6"
+
+"@babel/helper-skip-transparent-expression-wrappers@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz#778d87b3a758d90b471e7b9918f34a9a02eb5818"
+ integrity sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==
+ dependencies:
+ "@babel/types" "^7.18.9"
+
+"@babel/helper-split-export-declaration@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075"
+ integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==
+ dependencies:
+ "@babel/types" "^7.18.6"
+
+"@babel/helper-string-parser@^7.18.10":
+ version "7.18.10"
+ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56"
+ integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==
+
+"@babel/helper-validator-identifier@^7.18.6":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
+ integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
+
+"@babel/helper-validator-identifier@^7.24.5":
+ version "7.24.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz#08bb6612b11bdec78f3feed3db196da682454a5e"
+ integrity sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==
+
+"@babel/helper-validator-option@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8"
+ integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==
+
+"@babel/helper-wrap-function@^7.18.9":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz#89f18335cff1152373222f76a4b37799636ae8b1"
+ integrity sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==
+ dependencies:
+ "@babel/helper-function-name" "^7.19.0"
+ "@babel/template" "^7.18.10"
+ "@babel/traverse" "^7.19.0"
+ "@babel/types" "^7.19.0"
+
+"@babel/helpers@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.19.0.tgz#f30534657faf246ae96551d88dd31e9d1fa1fc18"
+ integrity sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==
+ dependencies:
+ "@babel/template" "^7.18.10"
+ "@babel/traverse" "^7.19.0"
+ "@babel/types" "^7.19.0"
+
+"@babel/highlight@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf"
+ integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.18.6"
+ chalk "^2.0.0"
+ js-tokens "^4.0.0"
+
+"@babel/parser@^7.16.4", "@babel/parser@^7.18.10", "@babel/parser@^7.18.4", "@babel/parser@^7.19.1":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.1.tgz#6f6d6c2e621aad19a92544cc217ed13f1aac5b4c"
+ integrity sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==
+
+"@babel/parser@^7.20.15", "@babel/parser@^7.21.3":
+ version "7.22.14"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.14.tgz#c7de58e8de106e88efca42ce17f0033209dfd245"
+ integrity sha512-1KucTHgOvaw/LzCVrEOAyXkr9rQlp0A1HiHRYnSUE9dmb8PvPW7o5sscg+5169r54n3vGlbx6GevTE/Iw/P3AQ==
+
+"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2"
+ integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50"
+ integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.9"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9"
+ "@babel/plugin-proposal-optional-chaining" "^7.18.9"
+
+"@babel/plugin-proposal-async-generator-functions@^7.19.1":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz#34f6f5174b688529342288cd264f80c9ea9fb4a7"
+ integrity sha512-0yu8vNATgLy4ivqMNBIwb1HebCelqN7YX8SL3FDXORv/RqT0zEEWUCH4GH44JsSrvCu6GqnAdR5EBFAPeNBB4Q==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.18.9"
+ "@babel/helper-plugin-utils" "^7.19.0"
+ "@babel/helper-remap-async-to-generator" "^7.18.9"
+ "@babel/plugin-syntax-async-generators" "^7.8.4"
+
+"@babel/plugin-proposal-class-properties@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3"
+ integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-proposal-class-static-block@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020"
+ integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/plugin-syntax-class-static-block" "^7.14.5"
+
+"@babel/plugin-proposal-dynamic-import@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94"
+ integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/plugin-syntax-dynamic-import" "^7.8.3"
+
+"@babel/plugin-proposal-export-namespace-from@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203"
+ integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.9"
+ "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
+
+"@babel/plugin-proposal-json-strings@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b"
+ integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/plugin-syntax-json-strings" "^7.8.3"
+
+"@babel/plugin-proposal-logical-assignment-operators@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23"
+ integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.9"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
+
+"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1"
+ integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
+
+"@babel/plugin-proposal-numeric-separator@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75"
+ integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/plugin-syntax-numeric-separator" "^7.10.4"
+
+"@babel/plugin-proposal-object-rest-spread@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz#f9434f6beb2c8cae9dfcf97d2a5941bbbf9ad4e7"
+ integrity sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==
+ dependencies:
+ "@babel/compat-data" "^7.18.8"
+ "@babel/helper-compilation-targets" "^7.18.9"
+ "@babel/helper-plugin-utils" "^7.18.9"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+ "@babel/plugin-transform-parameters" "^7.18.8"
+
+"@babel/plugin-proposal-optional-catch-binding@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb"
+ integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+
+"@babel/plugin-proposal-optional-chaining@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993"
+ integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.9"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+
+"@babel/plugin-proposal-private-methods@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea"
+ integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-proposal-private-property-in-object@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503"
+ integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.18.6"
+ "@babel/helper-create-class-features-plugin" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
+
+"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e"
+ integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-syntax-async-generators@^7.8.4":
+ version "7.8.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
+ integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-class-properties@^7.12.13":
+ version "7.12.13"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10"
+ integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.12.13"
+
+"@babel/plugin-syntax-class-static-block@^7.14.5":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406"
+ integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-syntax-dynamic-import@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
+ integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-export-namespace-from@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a"
+ integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.3"
+
+"@babel/plugin-syntax-import-assertions@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz#cd6190500a4fa2fe31990a963ffab4b63e4505e4"
+ integrity sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-syntax-json-strings@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a"
+ integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-logical-assignment-operators@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
+ integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9"
+ integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-numeric-separator@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97"
+ integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+"@babel/plugin-syntax-object-rest-spread@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871"
+ integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-optional-catch-binding@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1"
+ integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-optional-chaining@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a"
+ integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-private-property-in-object@^7.14.5":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad"
+ integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-syntax-top-level-await@^7.14.5":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c"
+ integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-transform-arrow-functions@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe"
+ integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-async-to-generator@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615"
+ integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==
+ dependencies:
+ "@babel/helper-module-imports" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/helper-remap-async-to-generator" "^7.18.6"
+
+"@babel/plugin-transform-block-scoped-functions@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8"
+ integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-block-scoping@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz#f9b7e018ac3f373c81452d6ada8bd5a18928926d"
+ integrity sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-classes@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz#0e61ec257fba409c41372175e7c1e606dc79bb20"
+ integrity sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.18.6"
+ "@babel/helper-compilation-targets" "^7.19.0"
+ "@babel/helper-environment-visitor" "^7.18.9"
+ "@babel/helper-function-name" "^7.19.0"
+ "@babel/helper-optimise-call-expression" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.19.0"
+ "@babel/helper-replace-supers" "^7.18.9"
+ "@babel/helper-split-export-declaration" "^7.18.6"
+ globals "^11.1.0"
+
+"@babel/plugin-transform-computed-properties@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e"
+ integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-destructuring@^7.18.13":
+ version "7.18.13"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz#9e03bc4a94475d62b7f4114938e6c5c33372cbf5"
+ integrity sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8"
+ integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-duplicate-keys@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e"
+ integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-exponentiation-operator@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd"
+ integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==
+ dependencies:
+ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-for-of@^7.18.8":
+ version "7.18.8"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1"
+ integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-function-name@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0"
+ integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==
+ dependencies:
+ "@babel/helper-compilation-targets" "^7.18.9"
+ "@babel/helper-function-name" "^7.18.9"
+ "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-literals@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc"
+ integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-member-expression-literals@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e"
+ integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-modules-amd@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz#8c91f8c5115d2202f277549848874027d7172d21"
+ integrity sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+ babel-plugin-dynamic-import-node "^2.3.3"
+
+"@babel/plugin-transform-modules-commonjs@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz#afd243afba166cca69892e24a8fd8c9f2ca87883"
+ integrity sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/helper-simple-access" "^7.18.6"
+ babel-plugin-dynamic-import-node "^2.3.3"
+
+"@babel/plugin-transform-modules-systemjs@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz#5f20b471284430f02d9c5059d9b9a16d4b085a1f"
+ integrity sha512-x9aiR0WXAWmOWsqcsnrzGR+ieaTMVyGyffPVA7F8cXAGt/UxefYv6uSHZLkAFChN5M5Iy1+wjE+xJuPt22H39A==
+ dependencies:
+ "@babel/helper-hoist-variables" "^7.18.6"
+ "@babel/helper-module-transforms" "^7.19.0"
+ "@babel/helper-plugin-utils" "^7.19.0"
+ "@babel/helper-validator-identifier" "^7.18.6"
+ babel-plugin-dynamic-import-node "^2.3.3"
+
+"@babel/plugin-transform-modules-umd@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9"
+ integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz#ec7455bab6cd8fb05c525a94876f435a48128888"
+ integrity sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.19.0"
+ "@babel/helper-plugin-utils" "^7.19.0"
+
+"@babel/plugin-transform-new-target@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8"
+ integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-object-super@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c"
+ integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/helper-replace-supers" "^7.18.6"
+
+"@babel/plugin-transform-parameters@^7.18.8":
+ version "7.18.8"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz#ee9f1a0ce6d78af58d0956a9378ea3427cccb48a"
+ integrity sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-property-literals@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3"
+ integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-regenerator@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73"
+ integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+ regenerator-transform "^0.15.0"
+
+"@babel/plugin-transform-reserved-words@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a"
+ integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-shorthand-properties@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9"
+ integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-spread@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6"
+ integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.19.0"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9"
+
+"@babel/plugin-transform-sticky-regex@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc"
+ integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-template-literals@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e"
+ integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-typeof-symbol@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0"
+ integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-unicode-escapes@^7.18.10":
+ version "7.18.10"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246"
+ integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-unicode-regex@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca"
+ integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/preset-env@^7.16.4":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.19.1.tgz#9f04c916f9c0205a48ebe5cc1be7768eb1983f67"
+ integrity sha512-c8B2c6D16Lp+Nt6HcD+nHl0VbPKVnNPTpszahuxJJnurfMtKeZ80A+qUv48Y7wqvS+dTFuLuaM9oYxyNHbCLWA==
+ dependencies:
+ "@babel/compat-data" "^7.19.1"
+ "@babel/helper-compilation-targets" "^7.19.1"
+ "@babel/helper-plugin-utils" "^7.19.0"
+ "@babel/helper-validator-option" "^7.18.6"
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6"
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9"
+ "@babel/plugin-proposal-async-generator-functions" "^7.19.1"
+ "@babel/plugin-proposal-class-properties" "^7.18.6"
+ "@babel/plugin-proposal-class-static-block" "^7.18.6"
+ "@babel/plugin-proposal-dynamic-import" "^7.18.6"
+ "@babel/plugin-proposal-export-namespace-from" "^7.18.9"
+ "@babel/plugin-proposal-json-strings" "^7.18.6"
+ "@babel/plugin-proposal-logical-assignment-operators" "^7.18.9"
+ "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6"
+ "@babel/plugin-proposal-numeric-separator" "^7.18.6"
+ "@babel/plugin-proposal-object-rest-spread" "^7.18.9"
+ "@babel/plugin-proposal-optional-catch-binding" "^7.18.6"
+ "@babel/plugin-proposal-optional-chaining" "^7.18.9"
+ "@babel/plugin-proposal-private-methods" "^7.18.6"
+ "@babel/plugin-proposal-private-property-in-object" "^7.18.6"
+ "@babel/plugin-proposal-unicode-property-regex" "^7.18.6"
+ "@babel/plugin-syntax-async-generators" "^7.8.4"
+ "@babel/plugin-syntax-class-properties" "^7.12.13"
+ "@babel/plugin-syntax-class-static-block" "^7.14.5"
+ "@babel/plugin-syntax-dynamic-import" "^7.8.3"
+ "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
+ "@babel/plugin-syntax-import-assertions" "^7.18.6"
+ "@babel/plugin-syntax-json-strings" "^7.8.3"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
+ "@babel/plugin-syntax-numeric-separator" "^7.10.4"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+ "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
+ "@babel/plugin-syntax-top-level-await" "^7.14.5"
+ "@babel/plugin-transform-arrow-functions" "^7.18.6"
+ "@babel/plugin-transform-async-to-generator" "^7.18.6"
+ "@babel/plugin-transform-block-scoped-functions" "^7.18.6"
+ "@babel/plugin-transform-block-scoping" "^7.18.9"
+ "@babel/plugin-transform-classes" "^7.19.0"
+ "@babel/plugin-transform-computed-properties" "^7.18.9"
+ "@babel/plugin-transform-destructuring" "^7.18.13"
+ "@babel/plugin-transform-dotall-regex" "^7.18.6"
+ "@babel/plugin-transform-duplicate-keys" "^7.18.9"
+ "@babel/plugin-transform-exponentiation-operator" "^7.18.6"
+ "@babel/plugin-transform-for-of" "^7.18.8"
+ "@babel/plugin-transform-function-name" "^7.18.9"
+ "@babel/plugin-transform-literals" "^7.18.9"
+ "@babel/plugin-transform-member-expression-literals" "^7.18.6"
+ "@babel/plugin-transform-modules-amd" "^7.18.6"
+ "@babel/plugin-transform-modules-commonjs" "^7.18.6"
+ "@babel/plugin-transform-modules-systemjs" "^7.19.0"
+ "@babel/plugin-transform-modules-umd" "^7.18.6"
+ "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.1"
+ "@babel/plugin-transform-new-target" "^7.18.6"
+ "@babel/plugin-transform-object-super" "^7.18.6"
+ "@babel/plugin-transform-parameters" "^7.18.8"
+ "@babel/plugin-transform-property-literals" "^7.18.6"
+ "@babel/plugin-transform-regenerator" "^7.18.6"
+ "@babel/plugin-transform-reserved-words" "^7.18.6"
+ "@babel/plugin-transform-shorthand-properties" "^7.18.6"
+ "@babel/plugin-transform-spread" "^7.19.0"
+ "@babel/plugin-transform-sticky-regex" "^7.18.6"
+ "@babel/plugin-transform-template-literals" "^7.18.9"
+ "@babel/plugin-transform-typeof-symbol" "^7.18.9"
+ "@babel/plugin-transform-unicode-escapes" "^7.18.10"
+ "@babel/plugin-transform-unicode-regex" "^7.18.6"
+ "@babel/preset-modules" "^0.1.5"
+ "@babel/types" "^7.19.0"
+ babel-plugin-polyfill-corejs2 "^0.3.3"
+ babel-plugin-polyfill-corejs3 "^0.6.0"
+ babel-plugin-polyfill-regenerator "^0.4.1"
+ core-js-compat "^3.25.1"
+ semver "^6.3.0"
+
+"@babel/preset-modules@^0.1.5":
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9"
+ integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-proposal-unicode-property-regex" "^7.4.4"
+ "@babel/plugin-transform-dotall-regex" "^7.4.4"
+ "@babel/types" "^7.4.4"
+ esutils "^2.0.2"
+
+"@babel/runtime@^7.13.10":
+ version "7.23.9"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7"
+ integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==
+ dependencies:
+ regenerator-runtime "^0.14.0"
+
+"@babel/runtime@^7.8.4":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259"
+ integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==
+ dependencies:
+ regenerator-runtime "^0.13.4"
+
+"@babel/template@^7.18.10":
+ version "7.18.10"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71"
+ integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==
+ dependencies:
+ "@babel/code-frame" "^7.18.6"
+ "@babel/parser" "^7.18.10"
+ "@babel/types" "^7.18.10"
+
+"@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.1.tgz#0fafe100a8c2a603b4718b1d9bf2568d1d193347"
+ integrity sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==
+ dependencies:
+ "@babel/code-frame" "^7.18.6"
+ "@babel/generator" "^7.19.0"
+ "@babel/helper-environment-visitor" "^7.18.9"
+ "@babel/helper-function-name" "^7.19.0"
+ "@babel/helper-hoist-variables" "^7.18.6"
+ "@babel/helper-split-export-declaration" "^7.18.6"
+ "@babel/parser" "^7.19.1"
+ "@babel/types" "^7.19.0"
+ debug "^4.1.0"
+ globals "^11.1.0"
+
+"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.4.4":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.0.tgz#75f21d73d73dc0351f3368d28db73465f4814600"
+ integrity sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==
+ dependencies:
+ "@babel/helper-string-parser" "^7.18.10"
+ "@babel/helper-validator-identifier" "^7.18.6"
+ to-fast-properties "^2.0.0"
+
+"@clack/core@^0.3.3":
+ version "0.3.4"
+ resolved "https://registry.yarnpkg.com/@clack/core/-/core-0.3.4.tgz#375e82fc8fe46650b37cab2f2ea8752c6b7f0450"
+ integrity sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==
+ dependencies:
+ picocolors "^1.0.0"
+ sisteransi "^1.0.5"
+
+"@clack/prompts@^0.7.0":
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/@clack/prompts/-/prompts-0.7.0.tgz#6aaef48ea803d91cce12bc80811cfcb8de2e75ea"
+ integrity sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA==
+ dependencies:
+ "@clack/core" "^0.3.3"
+ picocolors "^1.0.0"
+ sisteransi "^1.0.5"
+
+"@cypress/listr-verbose-renderer@0.4.1":
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#a77492f4b11dcc7c446a34b3e28721afd33c642a"
+ integrity sha512-EDiBsVPWC27DDLEJCo+dpl9ODHhdrwU57ccr9tspwCdG2ni0QVkf6LF0FGbhfujcjPxnXLIwsaks4sOrwrA4Qw==
+ dependencies:
+ chalk "^1.1.3"
+ cli-cursor "^1.0.2"
+ date-fns "^1.27.2"
+ figures "^1.7.0"
+
+"@cypress/xvfb@1.2.4":
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.4.tgz#2daf42e8275b39f4aa53c14214e557bd14e7748a"
+ integrity sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==
+ dependencies:
+ debug "^3.1.0"
+ lodash.once "^4.1.1"
+
+"@discoveryjs/json-ext@^0.5.0":
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
+ integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
+
+"@docsearch/css@3.2.1", "@docsearch/css@^3.0.0":
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.2.1.tgz#c05d7818b0e43b42f9efa2d82a11c36606b37b27"
+ integrity sha512-gaP6TxxwQC+K8D6TRx5WULUWKrcbzECOPA2KCVMuI+6C7dNiGUk5yXXzVhc5sld79XKYLnO9DRTI4mjXDYkh+g==
+
+"@docsearch/js@^3.0.0":
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/@docsearch/js/-/js-3.2.1.tgz#d6856fb6223c7a47091640264d5144d59806bc30"
+ integrity sha512-H1PekEtSeS0msetR2YGGey2w7jQ2wAKfGODJvQTygSwMgUZ+2DHpzUgeDyEBIXRIfaBcoQneqrzsljM62pm6Xg==
+ dependencies:
+ "@docsearch/react" "3.2.1"
+ preact "^10.0.0"
+
+"@docsearch/react@3.2.1":
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.2.1.tgz#112ad88db07367fa6fd933d67d58421d8d8289aa"
+ integrity sha512-EzTQ/y82s14IQC5XVestiK/kFFMe2aagoYFuTAIfIb/e+4FU7kSMKonRtLwsCiLQHmjvNQq+HO+33giJ5YVtaQ==
+ dependencies:
+ "@algolia/autocomplete-core" "1.7.1"
+ "@algolia/autocomplete-preset-algolia" "1.7.1"
+ "@docsearch/css" "3.2.1"
+ algoliasearch "^4.0.0"
+
+"@electron/get@^1.14.1":
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.14.1.tgz#16ba75f02dffb74c23965e72d617adc721d27f40"
+ integrity sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==
+ dependencies:
+ debug "^4.1.1"
+ env-paths "^2.2.0"
+ fs-extra "^8.1.0"
+ got "^9.6.0"
+ progress "^2.0.3"
+ semver "^6.2.0"
+ sumchecker "^3.0.1"
+ optionalDependencies:
+ global-agent "^3.0.0"
+ global-tunnel-ng "^2.7.1"
+
+"@es-joy/jsdoccomment@^0.43.0", "@es-joy/jsdoccomment@~0.43.1":
+ version "0.43.1"
+ resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.43.1.tgz#4b1979b7b4ff8b596fb19a3aa696a438e44608d7"
+ integrity sha512-I238eDtOolvCuvtxrnqtlBaw0BwdQuYqK7eA6XIonicMdOOOb75mqdIzkGDUbS04+1Di007rgm9snFRNeVrOog==
+ dependencies:
+ "@types/eslint" "^8.56.5"
+ "@types/estree" "^1.0.5"
+ "@typescript-eslint/types" "^7.2.0"
+ comment-parser "1.4.1"
+ esquery "^1.5.0"
+ jsdoc-type-pratt-parser "~4.0.0"
+
+"@esbuild/android-arm@0.15.9":
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.15.9.tgz#7e1221604ab88ed5021ead74fa8cca4405e1e431"
+ integrity sha512-VZPy/ETF3fBG5PiinIkA0W/tlsvlEgJccyN2DzWZEl0DlVKRbu91PvY2D6Lxgluj4w9QtYHjOWjAT44C+oQ+EQ==
+
+"@esbuild/linux-loong64@0.14.54":
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz#de2a4be678bd4d0d1ffbb86e6de779cde5999028"
+ integrity sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==
+
+"@esbuild/linux-loong64@0.15.9":
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.9.tgz#b658a97babf1f40783354af7039b84c3fdfc3fc3"
+ integrity sha512-O+NfmkfRrb3uSsTa4jE3WApidSe3N5++fyOVGP1SmMZi4A3BZELkhUUvj5hwmMuNdlpzAZ8iAPz2vmcR7DCFQA==
+
+"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
+ integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==
+ dependencies:
+ eslint-visitor-keys "^3.3.0"
+
+"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.0", "@eslint-community/regexpp@^4.6.1", "@eslint-community/regexpp@^4.8.0", "@eslint-community/regexpp@^4.9.1":
+ version "4.10.0"
+ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63"
+ integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==
+
+"@eslint/eslintrc@^3.0.2", "@eslint/eslintrc@^3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.1.0.tgz#dbd3482bfd91efa663cbe7aa1f506839868207b6"
+ integrity sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==
+ dependencies:
+ ajv "^6.12.4"
+ debug "^4.3.2"
+ espree "^10.0.1"
+ globals "^14.0.0"
+ ignore "^5.2.0"
+ import-fresh "^3.2.1"
+ js-yaml "^4.1.0"
+ minimatch "^3.1.2"
+ strip-json-comments "^3.1.1"
+
+"@eslint/js@9.3.0":
+ version "9.3.0"
+ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.3.0.tgz#2e8f65c9c55227abc4845b1513c69c32c679d8fe"
+ integrity sha512-niBqk8iwv96+yuTwjM6bWg8ovzAPF9qkICsGtcoa5/dmqcEMfdwNAX7+/OHcJHc7wj7XqPxH98oAHytFYlw6Sw==
+
+"@floating-ui/core@^1.1.0":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.4.2.tgz#2b52a12b843bdc1719375c8e20ed63206aac5ecf"
+ integrity sha512-olUakR5nr9v2ueVr1yomoJnBTkHGqHzL/iK4AhforiJS/wKJgFphAYpZHZzADLv/zNUFuQwqLH3bcoUhFh2E1Q==
+ dependencies:
+ "@floating-ui/utils" "^0.1.3"
+
+"@floating-ui/dom@~1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.1.1.tgz#66aa747e15894910869bf9144fc54fc7d6e9f975"
+ integrity sha512-TpIO93+DIujg3g7SykEAGZMDtbJRrmnYRCNYSjJlvIbGhBjRSNTLVbNeDQBrzy9qDgUbiWdc7KA0uZHZ2tJmiw==
+ dependencies:
+ "@floating-ui/core" "^1.1.0"
+
+"@floating-ui/utils@^0.1.3":
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.1.3.tgz#6ee493102b45d796d69f1f472d4bf64e5244500a"
+ integrity sha512-uvnFKtPgzLnpzzTRfhDlvXX0kLYi9lDRQbcDmT8iXl71Rx+uwSuaUIQl3DNC7w5OweAQ7XQMDObML+KaYDQfng==
+
+"@gar/promisify@^1.0.1":
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
+ integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
+
+"@hapi/hoek@^9.0.0":
+ version "9.3.0"
+ resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
+ integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==
+
+"@hapi/topo@^5.0.0":
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
+ integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
+ dependencies:
+ "@hapi/hoek" "^9.0.0"
+
+"@humanwhocodes/config-array@^0.13.0":
+ version "0.13.0"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748"
+ integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==
+ dependencies:
+ "@humanwhocodes/object-schema" "^2.0.3"
+ debug "^4.3.1"
+ minimatch "^3.0.5"
+
+"@humanwhocodes/module-importer@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
+ integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
+
+"@humanwhocodes/object-schema@^2.0.3":
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3"
+ integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==
+
+"@humanwhocodes/retry@^0.3.0":
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.0.tgz#6d86b8cb322660f03d3f0aa94b99bdd8e172d570"
+ integrity sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==
+
+"@hutson/parse-repository-url@^3.0.0":
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz#98c23c950a3d9b6c8f0daed06da6c3af06981340"
+ integrity sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==
+
+"@jridgewell/gen-mapping@^0.1.0":
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996"
+ integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==
+ dependencies:
+ "@jridgewell/set-array" "^1.0.0"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+
+"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2":
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
+ integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==
+ dependencies:
+ "@jridgewell/set-array" "^1.0.1"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/resolve-uri@^3.0.3":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
+ integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
+
+"@jridgewell/resolve-uri@^3.1.0":
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
+ integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
+
+"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
+ integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
+
+"@jridgewell/source-map@^0.3.2":
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb"
+ integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.0"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/source-map@^0.3.3":
+ version "0.3.5"
+ resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91"
+ integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.0"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/sourcemap-codec@^1.4.10":
+ version "1.4.14"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
+ integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
+
+"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15":
+ version "1.4.15"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
+ integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+
+"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.9":
+ version "0.3.15"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774"
+ integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.0.3"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+
+"@jridgewell/trace-mapping@^0.3.20":
+ version "0.3.22"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz#72a621e5de59f5f1ef792d0793a82ee20f645e4c"
+ integrity sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.1.0"
+ "@jridgewell/sourcemap-codec" "^1.4.14"
+
+"@jsdevtools/ez-spawn@^3.0.4":
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/@jsdevtools/ez-spawn/-/ez-spawn-3.0.4.tgz#5641eb26fee6d31ec29f6788eba849470c52c7ff"
+ integrity sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==
+ dependencies:
+ call-me-maybe "^1.0.1"
+ cross-spawn "^7.0.3"
+ string-argv "^0.3.1"
+ type-detect "^4.0.8"
+
+"@leichtgewicht/ip-codec@^2.0.1":
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b"
+ integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==
+
+"@lerna/add@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/add/-/add-4.0.0.tgz#c36f57d132502a57b9e7058d1548b7a565ef183f"
+ integrity sha512-cpmAH1iS3k8JBxNvnMqrGTTjbY/ZAiKa1ChJzFevMYY3eeqbvhsBKnBcxjRXtdrJ6bd3dCQM+ZtK+0i682Fhng==
+ dependencies:
+ "@lerna/bootstrap" "4.0.0"
+ "@lerna/command" "4.0.0"
+ "@lerna/filter-options" "4.0.0"
+ "@lerna/npm-conf" "4.0.0"
+ "@lerna/validation-error" "4.0.0"
+ dedent "^0.7.0"
+ npm-package-arg "^8.1.0"
+ p-map "^4.0.0"
+ pacote "^11.2.6"
+ semver "^7.3.4"
+
+"@lerna/bootstrap@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-4.0.0.tgz#5f5c5e2c6cfc8fcec50cb2fbe569a8c607101891"
+ integrity sha512-RkS7UbeM2vu+kJnHzxNRCLvoOP9yGNgkzRdy4UV2hNalD7EP41bLvRVOwRYQ7fhc2QcbhnKNdOBihYRL0LcKtw==
+ dependencies:
+ "@lerna/command" "4.0.0"
+ "@lerna/filter-options" "4.0.0"
+ "@lerna/has-npm-version" "4.0.0"
+ "@lerna/npm-install" "4.0.0"
+ "@lerna/package-graph" "4.0.0"
+ "@lerna/pulse-till-done" "4.0.0"
+ "@lerna/rimraf-dir" "4.0.0"
+ "@lerna/run-lifecycle" "4.0.0"
+ "@lerna/run-topologically" "4.0.0"
+ "@lerna/symlink-binary" "4.0.0"
+ "@lerna/symlink-dependencies" "4.0.0"
+ "@lerna/validation-error" "4.0.0"
+ dedent "^0.7.0"
+ get-port "^5.1.1"
+ multimatch "^5.0.0"
+ npm-package-arg "^8.1.0"
+ npmlog "^4.1.2"
+ p-map "^4.0.0"
+ p-map-series "^2.1.0"
+ p-waterfall "^2.1.1"
+ read-package-tree "^5.3.1"
+ semver "^7.3.4"
+
+"@lerna/changed@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-4.0.0.tgz#b9fc76cea39b9292a6cd263f03eb57af85c9270b"
+ integrity sha512-cD+KuPRp6qiPOD+BO6S6SN5cARspIaWSOqGBpGnYzLb4uWT8Vk4JzKyYtc8ym1DIwyoFXHosXt8+GDAgR8QrgQ==
+ dependencies:
+ "@lerna/collect-updates" "4.0.0"
+ "@lerna/command" "4.0.0"
+ "@lerna/listable" "4.0.0"
+ "@lerna/output" "4.0.0"
+
+"@lerna/check-working-tree@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/check-working-tree/-/check-working-tree-4.0.0.tgz#257e36a602c00142e76082a19358e3e1ae8dbd58"
+ integrity sha512-/++bxM43jYJCshBiKP5cRlCTwSJdRSxVmcDAXM+1oUewlZJVSVlnks5eO0uLxokVFvLhHlC5kHMc7gbVFPHv6Q==
+ dependencies:
+ "@lerna/collect-uncommitted" "4.0.0"
+ "@lerna/describe-ref" "4.0.0"
+ "@lerna/validation-error" "4.0.0"
+
+"@lerna/child-process@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-4.0.0.tgz#341b96a57dffbd9705646d316e231df6fa4df6e1"
+ integrity sha512-XtCnmCT9eyVsUUHx6y/CTBYdV9g2Cr/VxyseTWBgfIur92/YKClfEtJTbOh94jRT62hlKLqSvux/UhxXVh613Q==
+ dependencies:
+ chalk "^4.1.0"
+ execa "^5.0.0"
+ strong-log-transformer "^2.1.0"
+
+"@lerna/clean@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-4.0.0.tgz#8f778b6f2617aa2a936a6b5e085ae62498e57dc5"
+ integrity sha512-uugG2iN9k45ITx2jtd8nEOoAtca8hNlDCUM0N3lFgU/b1mEQYAPRkqr1qs4FLRl/Y50ZJ41wUz1eazS+d/0osA==
+ dependencies:
+ "@lerna/command" "4.0.0"
+ "@lerna/filter-options" "4.0.0"
+ "@lerna/prompt" "4.0.0"
+ "@lerna/pulse-till-done" "4.0.0"
+ "@lerna/rimraf-dir" "4.0.0"
+ p-map "^4.0.0"
+ p-map-series "^2.1.0"
+ p-waterfall "^2.1.1"
+
+"@lerna/cli@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/cli/-/cli-4.0.0.tgz#8eabd334558836c1664df23f19acb95e98b5bbf3"
+ integrity sha512-Neaw3GzFrwZiRZv2g7g6NwFjs3er1vhraIniEs0jjVLPMNC4eata0na3GfE5yibkM/9d3gZdmihhZdZ3EBdvYA==
+ dependencies:
+ "@lerna/global-options" "4.0.0"
+ dedent "^0.7.0"
+ npmlog "^4.1.2"
+ yargs "^16.2.0"
+
+"@lerna/collect-uncommitted@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/collect-uncommitted/-/collect-uncommitted-4.0.0.tgz#855cd64612969371cfc2453b90593053ff1ba779"
+ integrity sha512-ufSTfHZzbx69YNj7KXQ3o66V4RC76ffOjwLX0q/ab//61bObJ41n03SiQEhSlmpP+gmFbTJ3/7pTe04AHX9m/g==
+ dependencies:
+ "@lerna/child-process" "4.0.0"
+ chalk "^4.1.0"
+ npmlog "^4.1.2"
+
+"@lerna/collect-updates@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/collect-updates/-/collect-updates-4.0.0.tgz#8e208b1bafd98a372ff1177f7a5e288f6bea8041"
+ integrity sha512-bnNGpaj4zuxsEkyaCZLka9s7nMs58uZoxrRIPJ+nrmrZYp1V5rrd+7/NYTuunOhY2ug1sTBvTAxj3NZQ+JKnOw==
+ dependencies:
+ "@lerna/child-process" "4.0.0"
+ "@lerna/describe-ref" "4.0.0"
+ minimatch "^3.0.4"
+ npmlog "^4.1.2"
+ slash "^3.0.0"
+
+"@lerna/command@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/command/-/command-4.0.0.tgz#991c7971df8f5bf6ae6e42c808869a55361c1b98"
+ integrity sha512-LM9g3rt5FsPNFqIHUeRwWXLNHJ5NKzOwmVKZ8anSp4e1SPrv2HNc1V02/9QyDDZK/w+5POXH5lxZUI1CHaOK/A==
+ dependencies:
+ "@lerna/child-process" "4.0.0"
+ "@lerna/package-graph" "4.0.0"
+ "@lerna/project" "4.0.0"
+ "@lerna/validation-error" "4.0.0"
+ "@lerna/write-log-file" "4.0.0"
+ clone-deep "^4.0.1"
+ dedent "^0.7.0"
+ execa "^5.0.0"
+ is-ci "^2.0.0"
+ npmlog "^4.1.2"
+
+"@lerna/conventional-commits@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/conventional-commits/-/conventional-commits-4.0.0.tgz#660fb2c7b718cb942ead70110df61f18c6f99750"
+ integrity sha512-CSUQRjJHFrH8eBn7+wegZLV3OrNc0Y1FehYfYGhjLE2SIfpCL4bmfu/ViYuHh9YjwHaA+4SX6d3hR+xkeseKmw==
+ dependencies:
+ "@lerna/validation-error" "4.0.0"
+ conventional-changelog-angular "^5.0.12"
+ conventional-changelog-core "^4.2.2"
+ conventional-recommended-bump "^6.1.0"
+ fs-extra "^9.1.0"
+ get-stream "^6.0.0"
+ lodash.template "^4.5.0"
+ npm-package-arg "^8.1.0"
+ npmlog "^4.1.2"
+ pify "^5.0.0"
+ semver "^7.3.4"
+
+"@lerna/create-symlink@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/create-symlink/-/create-symlink-4.0.0.tgz#8c5317ce5ae89f67825443bd7651bf4121786228"
+ integrity sha512-I0phtKJJdafUiDwm7BBlEUOtogmu8+taxq6PtIrxZbllV9hWg59qkpuIsiFp+no7nfRVuaasNYHwNUhDAVQBig==
+ dependencies:
+ cmd-shim "^4.1.0"
+ fs-extra "^9.1.0"
+ npmlog "^4.1.2"
+
+"@lerna/create@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/create/-/create-4.0.0.tgz#b6947e9b5dfb6530321952998948c3e63d64d730"
+ integrity sha512-mVOB1niKByEUfxlbKTM1UNECWAjwUdiioIbRQZEeEabtjCL69r9rscIsjlGyhGWCfsdAG5wfq4t47nlDXdLLag==
+ dependencies:
+ "@lerna/child-process" "4.0.0"
+ "@lerna/command" "4.0.0"
+ "@lerna/npm-conf" "4.0.0"
+ "@lerna/validation-error" "4.0.0"
+ dedent "^0.7.0"
+ fs-extra "^9.1.0"
+ globby "^11.0.2"
+ init-package-json "^2.0.2"
+ npm-package-arg "^8.1.0"
+ p-reduce "^2.1.0"
+ pacote "^11.2.6"
+ pify "^5.0.0"
+ semver "^7.3.4"
+ slash "^3.0.0"
+ validate-npm-package-license "^3.0.4"
+ validate-npm-package-name "^3.0.0"
+ whatwg-url "^8.4.0"
+ yargs-parser "20.2.4"
+
+"@lerna/describe-ref@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/describe-ref/-/describe-ref-4.0.0.tgz#53c53b4ea65fdceffa072a62bfebe6772c45d9ec"
+ integrity sha512-eTU5+xC4C5Gcgz+Ey4Qiw9nV2B4JJbMulsYJMW8QjGcGh8zudib7Sduj6urgZXUYNyhYpRs+teci9M2J8u+UvQ==
+ dependencies:
+ "@lerna/child-process" "4.0.0"
+ npmlog "^4.1.2"
+
+"@lerna/diff@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-4.0.0.tgz#6d3071817aaa4205a07bf77cfc6e932796d48b92"
+ integrity sha512-jYPKprQVg41+MUMxx6cwtqsNm0Yxx9GDEwdiPLwcUTFx+/qKCEwifKNJ1oGIPBxyEHX2PFCOjkK39lHoj2qiag==
+ dependencies:
+ "@lerna/child-process" "4.0.0"
+ "@lerna/command" "4.0.0"
+ "@lerna/validation-error" "4.0.0"
+ npmlog "^4.1.2"
+
+"@lerna/exec@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-4.0.0.tgz#eb6cb95cb92d42590e9e2d628fcaf4719d4a8be6"
+ integrity sha512-VGXtL/b/JfY84NB98VWZpIExfhLOzy0ozm/0XaS4a2SmkAJc5CeUfrhvHxxkxiTBLkU+iVQUyYEoAT0ulQ8PCw==
+ dependencies:
+ "@lerna/child-process" "4.0.0"
+ "@lerna/command" "4.0.0"
+ "@lerna/filter-options" "4.0.0"
+ "@lerna/profiler" "4.0.0"
+ "@lerna/run-topologically" "4.0.0"
+ "@lerna/validation-error" "4.0.0"
+ p-map "^4.0.0"
+
+"@lerna/filter-options@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/filter-options/-/filter-options-4.0.0.tgz#ac94cc515d7fa3b47e2f7d74deddeabb1de5e9e6"
+ integrity sha512-vV2ANOeZhOqM0rzXnYcFFCJ/kBWy/3OA58irXih9AMTAlQLymWAK0akWybl++sUJ4HB9Hx12TOqaXbYS2NM5uw==
+ dependencies:
+ "@lerna/collect-updates" "4.0.0"
+ "@lerna/filter-packages" "4.0.0"
+ dedent "^0.7.0"
+ npmlog "^4.1.2"
+
+"@lerna/filter-packages@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/filter-packages/-/filter-packages-4.0.0.tgz#b1f70d70e1de9cdd36a4e50caa0ac501f8d012f2"
+ integrity sha512-+4AJIkK7iIiOaqCiVTYJxh/I9qikk4XjNQLhE3kixaqgMuHl1NQ99qXRR0OZqAWB9mh8Z1HA9bM5K1HZLBTOqA==
+ dependencies:
+ "@lerna/validation-error" "4.0.0"
+ multimatch "^5.0.0"
+ npmlog "^4.1.2"
+
+"@lerna/get-npm-exec-opts@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-4.0.0.tgz#dc955be94a4ae75c374ef9bce91320887d34608f"
+ integrity sha512-yvmkerU31CTWS2c7DvmAWmZVeclPBqI7gPVr5VATUKNWJ/zmVcU4PqbYoLu92I9Qc4gY1TuUplMNdNuZTSL7IQ==
+ dependencies:
+ npmlog "^4.1.2"
+
+"@lerna/get-packed@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/get-packed/-/get-packed-4.0.0.tgz#0989d61624ac1f97e393bdad2137c49cd7a37823"
+ integrity sha512-rfWONRsEIGyPJTxFzC8ECb3ZbsDXJbfqWYyeeQQDrJRPnEJErlltRLPLgC2QWbxFgFPsoDLeQmFHJnf0iDfd8w==
+ dependencies:
+ fs-extra "^9.1.0"
+ ssri "^8.0.1"
+ tar "^6.1.0"
+
+"@lerna/github-client@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/github-client/-/github-client-4.0.0.tgz#2ced67721363ef70f8e12ffafce4410918f4a8a4"
+ integrity sha512-2jhsldZtTKXYUBnOm23Lb0Fx8G4qfSXF9y7UpyUgWUj+YZYd+cFxSuorwQIgk5P4XXrtVhsUesIsli+BYSThiw==
+ dependencies:
+ "@lerna/child-process" "4.0.0"
+ "@octokit/plugin-enterprise-rest" "^6.0.1"
+ "@octokit/rest" "^18.1.0"
+ git-url-parse "^11.4.4"
+ npmlog "^4.1.2"
+
+"@lerna/gitlab-client@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/gitlab-client/-/gitlab-client-4.0.0.tgz#00dad73379c7b38951d4b4ded043504c14e2b67d"
+ integrity sha512-OMUpGSkeDWFf7BxGHlkbb35T7YHqVFCwBPSIR6wRsszY8PAzCYahtH3IaJzEJyUg6vmZsNl0FSr3pdA2skhxqA==
+ dependencies:
+ node-fetch "^2.6.1"
+ npmlog "^4.1.2"
+ whatwg-url "^8.4.0"
+
+"@lerna/global-options@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/global-options/-/global-options-4.0.0.tgz#c7d8b0de6a01d8a845e2621ea89e7f60f18c6a5f"
+ integrity sha512-TRMR8afAHxuYBHK7F++Ogop2a82xQjoGna1dvPOY6ltj/pEx59pdgcJfYcynYqMkFIk8bhLJJN9/ndIfX29FTQ==
+
+"@lerna/has-npm-version@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/has-npm-version/-/has-npm-version-4.0.0.tgz#d3fc3292c545eb28bd493b36e6237cf0279f631c"
+ integrity sha512-LQ3U6XFH8ZmLCsvsgq1zNDqka0Xzjq5ibVN+igAI5ccRWNaUsE/OcmsyMr50xAtNQMYMzmpw5GVLAivT2/YzCg==
+ dependencies:
+ "@lerna/child-process" "4.0.0"
+ semver "^7.3.4"
+
+"@lerna/import@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/import/-/import-4.0.0.tgz#bde656c4a451fa87ae41733ff8a8da60547c5465"
+ integrity sha512-FaIhd+4aiBousKNqC7TX1Uhe97eNKf5/SC7c5WZANVWtC7aBWdmswwDt3usrzCNpj6/Wwr9EtEbYROzxKH8ffg==
+ dependencies:
+ "@lerna/child-process" "4.0.0"
+ "@lerna/command" "4.0.0"
+ "@lerna/prompt" "4.0.0"
+ "@lerna/pulse-till-done" "4.0.0"
+ "@lerna/validation-error" "4.0.0"
+ dedent "^0.7.0"
+ fs-extra "^9.1.0"
+ p-map-series "^2.1.0"
+
+"@lerna/info@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/info/-/info-4.0.0.tgz#b9fb0e479d60efe1623603958a831a88b1d7f1fc"
+ integrity sha512-8Uboa12kaCSZEn4XRfPz5KU9XXoexSPS4oeYGj76s2UQb1O1GdnEyfjyNWoUl1KlJ2i/8nxUskpXIftoFYH0/Q==
+ dependencies:
+ "@lerna/command" "4.0.0"
+ "@lerna/output" "4.0.0"
+ envinfo "^7.7.4"
+
+"@lerna/init@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/init/-/init-4.0.0.tgz#dadff67e6dfb981e8ccbe0e6a310e837962f6c7a"
+ integrity sha512-wY6kygop0BCXupzWj5eLvTUqdR7vIAm0OgyV9WHpMYQGfs1V22jhztt8mtjCloD/O0nEe4tJhdG62XU5aYmPNQ==
+ dependencies:
+ "@lerna/child-process" "4.0.0"
+ "@lerna/command" "4.0.0"
+ fs-extra "^9.1.0"
+ p-map "^4.0.0"
+ write-json-file "^4.3.0"
+
+"@lerna/link@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/link/-/link-4.0.0.tgz#c3a38aabd44279d714e90f2451e31b63f0fb65ba"
+ integrity sha512-KlvPi7XTAcVOByfaLlOeYOfkkDcd+bejpHMCd1KcArcFTwijOwXOVi24DYomIeHvy6HsX/IUquJ4PPUJIeB4+w==
+ dependencies:
+ "@lerna/command" "4.0.0"
+ "@lerna/package-graph" "4.0.0"
+ "@lerna/symlink-dependencies" "4.0.0"
+ p-map "^4.0.0"
+ slash "^3.0.0"
+
+"@lerna/list@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/list/-/list-4.0.0.tgz#24b4e6995bd73f81c556793fe502b847efd9d1d7"
+ integrity sha512-L2B5m3P+U4Bif5PultR4TI+KtW+SArwq1i75QZ78mRYxPc0U/piau1DbLOmwrdqr99wzM49t0Dlvl6twd7GHFg==
+ dependencies:
+ "@lerna/command" "4.0.0"
+ "@lerna/filter-options" "4.0.0"
+ "@lerna/listable" "4.0.0"
+ "@lerna/output" "4.0.0"
+
+"@lerna/listable@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/listable/-/listable-4.0.0.tgz#d00d6cb4809b403f2b0374fc521a78e318b01214"
+ integrity sha512-/rPOSDKsOHs5/PBLINZOkRIX1joOXUXEtyUs5DHLM8q6/RP668x/1lFhw6Dx7/U+L0+tbkpGtZ1Yt0LewCLgeQ==
+ dependencies:
+ "@lerna/query-graph" "4.0.0"
+ chalk "^4.1.0"
+ columnify "^1.5.4"
+
+"@lerna/log-packed@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/log-packed/-/log-packed-4.0.0.tgz#95168fe2e26ac6a71e42f4be857519b77e57a09f"
+ integrity sha512-+dpCiWbdzgMAtpajLToy9PO713IHoE6GV/aizXycAyA07QlqnkpaBNZ8DW84gHdM1j79TWockGJo9PybVhrrZQ==
+ dependencies:
+ byte-size "^7.0.0"
+ columnify "^1.5.4"
+ has-unicode "^2.0.1"
+ npmlog "^4.1.2"
+
+"@lerna/npm-conf@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/npm-conf/-/npm-conf-4.0.0.tgz#b259fd1e1cee2bf5402b236e770140ff9ade7fd2"
+ integrity sha512-uS7H02yQNq3oejgjxAxqq/jhwGEE0W0ntr8vM3EfpCW1F/wZruwQw+7bleJQ9vUBjmdXST//tk8mXzr5+JXCfw==
+ dependencies:
+ config-chain "^1.1.12"
+ pify "^5.0.0"
+
+"@lerna/npm-dist-tag@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/npm-dist-tag/-/npm-dist-tag-4.0.0.tgz#d1e99b4eccd3414142f0548ad331bf2d53f3257a"
+ integrity sha512-F20sg28FMYTgXqEQihgoqSfwmq+Id3zT23CnOwD+XQMPSy9IzyLf1fFVH319vXIw6NF6Pgs4JZN2Qty6/CQXGw==
+ dependencies:
+ "@lerna/otplease" "4.0.0"
+ npm-package-arg "^8.1.0"
+ npm-registry-fetch "^9.0.0"
+ npmlog "^4.1.2"
+
+"@lerna/npm-install@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/npm-install/-/npm-install-4.0.0.tgz#31180be3ab3b7d1818a1a0c206aec156b7094c78"
+ integrity sha512-aKNxq2j3bCH3eXl3Fmu4D54s/YLL9WSwV8W7X2O25r98wzrO38AUN6AB9EtmAx+LV/SP15et7Yueg9vSaanRWg==
+ dependencies:
+ "@lerna/child-process" "4.0.0"
+ "@lerna/get-npm-exec-opts" "4.0.0"
+ fs-extra "^9.1.0"
+ npm-package-arg "^8.1.0"
+ npmlog "^4.1.2"
+ signal-exit "^3.0.3"
+ write-pkg "^4.0.0"
+
+"@lerna/npm-publish@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/npm-publish/-/npm-publish-4.0.0.tgz#84eb62e876fe949ae1fd62c60804423dbc2c4472"
+ integrity sha512-vQb7yAPRo5G5r77DRjHITc9piR9gvEKWrmfCH7wkfBnGWEqu7n8/4bFQ7lhnkujvc8RXOsYpvbMQkNfkYibD/w==
+ dependencies:
+ "@lerna/otplease" "4.0.0"
+ "@lerna/run-lifecycle" "4.0.0"
+ fs-extra "^9.1.0"
+ libnpmpublish "^4.0.0"
+ npm-package-arg "^8.1.0"
+ npmlog "^4.1.2"
+ pify "^5.0.0"
+ read-package-json "^3.0.0"
+
+"@lerna/npm-run-script@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/npm-run-script/-/npm-run-script-4.0.0.tgz#dfebf4f4601442e7c0b5214f9fb0d96c9350743b"
+ integrity sha512-Jmyh9/IwXJjOXqKfIgtxi0bxi1pUeKe5bD3S81tkcy+kyng/GNj9WSqD5ZggoNP2NP//s4CLDAtUYLdP7CU9rA==
+ dependencies:
+ "@lerna/child-process" "4.0.0"
+ "@lerna/get-npm-exec-opts" "4.0.0"
+ npmlog "^4.1.2"
+
+"@lerna/otplease@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/otplease/-/otplease-4.0.0.tgz#84972eb43448f8a1077435ba1c5e59233b725850"
+ integrity sha512-Sgzbqdk1GH4psNiT6hk+BhjOfIr/5KhGBk86CEfHNJTk9BK4aZYyJD4lpDbDdMjIV4g03G7pYoqHzH765T4fxw==
+ dependencies:
+ "@lerna/prompt" "4.0.0"
+
+"@lerna/output@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/output/-/output-4.0.0.tgz#b1d72215c0e35483e4f3e9994debc82c621851f2"
+ integrity sha512-Un1sHtO1AD7buDQrpnaYTi2EG6sLF+KOPEAMxeUYG5qG3khTs2Zgzq5WE3dt2N/bKh7naESt20JjIW6tBELP0w==
+ dependencies:
+ npmlog "^4.1.2"
+
+"@lerna/pack-directory@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/pack-directory/-/pack-directory-4.0.0.tgz#8b617db95d20792f043aaaa13a9ccc0e04cb4c74"
+ integrity sha512-NJrmZNmBHS+5aM+T8N6FVbaKFScVqKlQFJNY2k7nsJ/uklNKsLLl6VhTQBPwMTbf6Tf7l6bcKzpy7aePuq9UiQ==
+ dependencies:
+ "@lerna/get-packed" "4.0.0"
+ "@lerna/package" "4.0.0"
+ "@lerna/run-lifecycle" "4.0.0"
+ npm-packlist "^2.1.4"
+ npmlog "^4.1.2"
+ tar "^6.1.0"
+ temp-write "^4.0.0"
+
+"@lerna/package-graph@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/package-graph/-/package-graph-4.0.0.tgz#16a00253a8ac810f72041481cb46bcee8d8123dd"
+ integrity sha512-QED2ZCTkfXMKFoTGoccwUzjHtZMSf3UKX14A4/kYyBms9xfFsesCZ6SLI5YeySEgcul8iuIWfQFZqRw+Qrjraw==
+ dependencies:
+ "@lerna/prerelease-id-from-version" "4.0.0"
+ "@lerna/validation-error" "4.0.0"
+ npm-package-arg "^8.1.0"
+ npmlog "^4.1.2"
+ semver "^7.3.4"
+
+"@lerna/package@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/package/-/package-4.0.0.tgz#1b4c259c4bcff45c876ee1d591a043aacbc0d6b7"
+ integrity sha512-l0M/izok6FlyyitxiQKr+gZLVFnvxRQdNhzmQ6nRnN9dvBJWn+IxxpM+cLqGACatTnyo9LDzNTOj2Db3+s0s8Q==
+ dependencies:
+ load-json-file "^6.2.0"
+ npm-package-arg "^8.1.0"
+ write-pkg "^4.0.0"
+
+"@lerna/prerelease-id-from-version@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-4.0.0.tgz#c7e0676fcee1950d85630e108eddecdd5b48c916"
+ integrity sha512-GQqguzETdsYRxOSmdFZ6zDBXDErIETWOqomLERRY54f4p+tk4aJjoVdd9xKwehC9TBfIFvlRbL1V9uQGHh1opg==
+ dependencies:
+ semver "^7.3.4"
+
+"@lerna/profiler@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/profiler/-/profiler-4.0.0.tgz#8a53ab874522eae15d178402bff90a14071908e9"
+ integrity sha512-/BaEbqnVh1LgW/+qz8wCuI+obzi5/vRE8nlhjPzdEzdmWmZXuCKyWSEzAyHOJWw1ntwMiww5dZHhFQABuoFz9Q==
+ dependencies:
+ fs-extra "^9.1.0"
+ npmlog "^4.1.2"
+ upath "^2.0.1"
+
+"@lerna/project@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/project/-/project-4.0.0.tgz#ff84893935833533a74deff30c0e64ddb7f0ba6b"
+ integrity sha512-o0MlVbDkD5qRPkFKlBZsXZjoNTWPyuL58564nSfZJ6JYNmgAptnWPB2dQlAc7HWRZkmnC2fCkEdoU+jioPavbg==
+ dependencies:
+ "@lerna/package" "4.0.0"
+ "@lerna/validation-error" "4.0.0"
+ cosmiconfig "^7.0.0"
+ dedent "^0.7.0"
+ dot-prop "^6.0.1"
+ glob-parent "^5.1.1"
+ globby "^11.0.2"
+ load-json-file "^6.2.0"
+ npmlog "^4.1.2"
+ p-map "^4.0.0"
+ resolve-from "^5.0.0"
+ write-json-file "^4.3.0"
+
+"@lerna/prompt@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/prompt/-/prompt-4.0.0.tgz#5ec69a803f3f0db0ad9f221dad64664d3daca41b"
+ integrity sha512-4Ig46oCH1TH5M7YyTt53fT6TuaKMgqUUaqdgxvp6HP6jtdak6+amcsqB8YGz2eQnw/sdxunx84DfI9XpoLj4bQ==
+ dependencies:
+ inquirer "^7.3.3"
+ npmlog "^4.1.2"
+
+"@lerna/publish@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-4.0.0.tgz#f67011305adeba120066a3b6d984a5bb5fceef65"
+ integrity sha512-K8jpqjHrChH22qtkytA5GRKIVFEtqBF6JWj1I8dWZtHs4Jywn8yB1jQ3BAMLhqmDJjWJtRck0KXhQQKzDK2UPg==
+ dependencies:
+ "@lerna/check-working-tree" "4.0.0"
+ "@lerna/child-process" "4.0.0"
+ "@lerna/collect-updates" "4.0.0"
+ "@lerna/command" "4.0.0"
+ "@lerna/describe-ref" "4.0.0"
+ "@lerna/log-packed" "4.0.0"
+ "@lerna/npm-conf" "4.0.0"
+ "@lerna/npm-dist-tag" "4.0.0"
+ "@lerna/npm-publish" "4.0.0"
+ "@lerna/otplease" "4.0.0"
+ "@lerna/output" "4.0.0"
+ "@lerna/pack-directory" "4.0.0"
+ "@lerna/prerelease-id-from-version" "4.0.0"
+ "@lerna/prompt" "4.0.0"
+ "@lerna/pulse-till-done" "4.0.0"
+ "@lerna/run-lifecycle" "4.0.0"
+ "@lerna/run-topologically" "4.0.0"
+ "@lerna/validation-error" "4.0.0"
+ "@lerna/version" "4.0.0"
+ fs-extra "^9.1.0"
+ libnpmaccess "^4.0.1"
+ npm-package-arg "^8.1.0"
+ npm-registry-fetch "^9.0.0"
+ npmlog "^4.1.2"
+ p-map "^4.0.0"
+ p-pipe "^3.1.0"
+ pacote "^11.2.6"
+ semver "^7.3.4"
+
+"@lerna/pulse-till-done@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/pulse-till-done/-/pulse-till-done-4.0.0.tgz#04bace7d483a8205c187b806bcd8be23d7bb80a3"
+ integrity sha512-Frb4F7QGckaybRhbF7aosLsJ5e9WuH7h0KUkjlzSByVycxY91UZgaEIVjS2oN9wQLrheLMHl6SiFY0/Pvo0Cxg==
+ dependencies:
+ npmlog "^4.1.2"
+
+"@lerna/query-graph@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/query-graph/-/query-graph-4.0.0.tgz#09dd1c819ac5ee3f38db23931143701f8a6eef63"
+ integrity sha512-YlP6yI3tM4WbBmL9GCmNDoeQyzcyg1e4W96y/PKMZa5GbyUvkS2+Jc2kwPD+5KcXou3wQZxSPzR3Te5OenaDdg==
+ dependencies:
+ "@lerna/package-graph" "4.0.0"
+
+"@lerna/resolve-symlink@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/resolve-symlink/-/resolve-symlink-4.0.0.tgz#6d006628a210c9b821964657a9e20a8c9a115e14"
+ integrity sha512-RtX8VEUzqT+uLSCohx8zgmjc6zjyRlh6i/helxtZTMmc4+6O4FS9q5LJas2uGO2wKvBlhcD6siibGt7dIC3xZA==
+ dependencies:
+ fs-extra "^9.1.0"
+ npmlog "^4.1.2"
+ read-cmd-shim "^2.0.0"
+
+"@lerna/rimraf-dir@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/rimraf-dir/-/rimraf-dir-4.0.0.tgz#2edf3b62d4eb0ef4e44e430f5844667d551ec25a"
+ integrity sha512-QNH9ABWk9mcMJh2/muD9iYWBk1oQd40y6oH+f3wwmVGKYU5YJD//+zMiBI13jxZRtwBx0vmBZzkBkK1dR11cBg==
+ dependencies:
+ "@lerna/child-process" "4.0.0"
+ npmlog "^4.1.2"
+ path-exists "^4.0.0"
+ rimraf "^3.0.2"
+
+"@lerna/run-lifecycle@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/run-lifecycle/-/run-lifecycle-4.0.0.tgz#e648a46f9210a9bcd7c391df6844498cb5079334"
+ integrity sha512-IwxxsajjCQQEJAeAaxF8QdEixfI7eLKNm4GHhXHrgBu185JcwScFZrj9Bs+PFKxwb+gNLR4iI5rpUdY8Y0UdGQ==
+ dependencies:
+ "@lerna/npm-conf" "4.0.0"
+ npm-lifecycle "^3.1.5"
+ npmlog "^4.1.2"
+
+"@lerna/run-topologically@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/run-topologically/-/run-topologically-4.0.0.tgz#af846eeee1a09b0c2be0d1bfb5ef0f7b04bb1827"
+ integrity sha512-EVZw9hGwo+5yp+VL94+NXRYisqgAlj0jWKWtAIynDCpghRxCE5GMO3xrQLmQgqkpUl9ZxQFpICgYv5DW4DksQA==
+ dependencies:
+ "@lerna/query-graph" "4.0.0"
+ p-queue "^6.6.2"
+
+"@lerna/run@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/run/-/run-4.0.0.tgz#4bc7fda055a729487897c23579694f6183c91262"
+ integrity sha512-9giulCOzlMPzcZS/6Eov6pxE9gNTyaXk0Man+iCIdGJNMrCnW7Dme0Z229WWP/UoxDKg71F2tMsVVGDiRd8fFQ==
+ dependencies:
+ "@lerna/command" "4.0.0"
+ "@lerna/filter-options" "4.0.0"
+ "@lerna/npm-run-script" "4.0.0"
+ "@lerna/output" "4.0.0"
+ "@lerna/profiler" "4.0.0"
+ "@lerna/run-topologically" "4.0.0"
+ "@lerna/timer" "4.0.0"
+ "@lerna/validation-error" "4.0.0"
+ p-map "^4.0.0"
+
+"@lerna/symlink-binary@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/symlink-binary/-/symlink-binary-4.0.0.tgz#21009f62d53a425f136cb4c1a32c6b2a0cc02d47"
+ integrity sha512-zualodWC4q1QQc1pkz969hcFeWXOsVYZC5AWVtAPTDfLl+TwM7eG/O6oP+Rr3fFowspxo6b1TQ6sYfDV6HXNWA==
+ dependencies:
+ "@lerna/create-symlink" "4.0.0"
+ "@lerna/package" "4.0.0"
+ fs-extra "^9.1.0"
+ p-map "^4.0.0"
+
+"@lerna/symlink-dependencies@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/symlink-dependencies/-/symlink-dependencies-4.0.0.tgz#8910eca084ae062642d0490d8972cf2d98e9ebbd"
+ integrity sha512-BABo0MjeUHNAe2FNGty1eantWp8u83BHSeIMPDxNq0MuW2K3CiQRaeWT3EGPAzXpGt0+hVzBrA6+OT0GPn7Yuw==
+ dependencies:
+ "@lerna/create-symlink" "4.0.0"
+ "@lerna/resolve-symlink" "4.0.0"
+ "@lerna/symlink-binary" "4.0.0"
+ fs-extra "^9.1.0"
+ p-map "^4.0.0"
+ p-map-series "^2.1.0"
+
+"@lerna/timer@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/timer/-/timer-4.0.0.tgz#a52e51bfcd39bfd768988049ace7b15c1fd7a6da"
+ integrity sha512-WFsnlaE7SdOvjuyd05oKt8Leg3ENHICnvX3uYKKdByA+S3g+TCz38JsNs7OUZVt+ba63nC2nbXDlUnuT2Xbsfg==
+
+"@lerna/validation-error@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/validation-error/-/validation-error-4.0.0.tgz#af9d62fe8304eaa2eb9a6ba1394f9aa807026d35"
+ integrity sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==
+ dependencies:
+ npmlog "^4.1.2"
+
+"@lerna/version@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/version/-/version-4.0.0.tgz#532659ec6154d8a8789c5ab53878663e244e3228"
+ integrity sha512-otUgiqs5W9zGWJZSCCMRV/2Zm2A9q9JwSDS7s/tlKq4mWCYriWo7+wsHEA/nPTMDyYyBO5oyZDj+3X50KDUzeA==
+ dependencies:
+ "@lerna/check-working-tree" "4.0.0"
+ "@lerna/child-process" "4.0.0"
+ "@lerna/collect-updates" "4.0.0"
+ "@lerna/command" "4.0.0"
+ "@lerna/conventional-commits" "4.0.0"
+ "@lerna/github-client" "4.0.0"
+ "@lerna/gitlab-client" "4.0.0"
+ "@lerna/output" "4.0.0"
+ "@lerna/prerelease-id-from-version" "4.0.0"
+ "@lerna/prompt" "4.0.0"
+ "@lerna/run-lifecycle" "4.0.0"
+ "@lerna/run-topologically" "4.0.0"
+ "@lerna/validation-error" "4.0.0"
+ chalk "^4.1.0"
+ dedent "^0.7.0"
+ load-json-file "^6.2.0"
+ minimatch "^3.0.4"
+ npmlog "^4.1.2"
+ p-map "^4.0.0"
+ p-pipe "^3.1.0"
+ p-reduce "^2.1.0"
+ p-waterfall "^2.1.1"
+ semver "^7.3.4"
+ slash "^3.0.0"
+ temp-write "^4.0.0"
+ write-json-file "^4.3.0"
+
+"@lerna/write-log-file@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@lerna/write-log-file/-/write-log-file-4.0.0.tgz#18221a38a6a307d6b0a5844dd592ad53fa27091e"
+ integrity sha512-XRG5BloiArpXRakcnPHmEHJp+4AtnhRtpDIHSghmXD5EichI1uD73J7FgPp30mm2pDRq3FdqB0NbwSEsJ9xFQg==
+ dependencies:
+ npmlog "^4.1.2"
+ write-file-atomic "^3.0.3"
+
+"@nodelib/fs.scandir@2.1.5":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
+ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+ dependencies:
+ "@nodelib/fs.stat" "2.0.5"
+ run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
+ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
+"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8":
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.5"
+ fastq "^1.6.0"
+
+"@npmcli/ci-detect@^1.0.0":
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/@npmcli/ci-detect/-/ci-detect-1.4.0.tgz#18478bbaa900c37bfbd8a2006a6262c62e8b0fe1"
+ integrity sha512-3BGrt6FLjqM6br5AhWRKTr3u5GIVkjRYeAFrMp3HjnfICrg4xOrVRwFavKT6tsp++bq5dluL5t8ME/Nha/6c1Q==
+
+"@npmcli/fs@^1.0.0":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257"
+ integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==
+ dependencies:
+ "@gar/promisify" "^1.0.1"
+ semver "^7.3.5"
+
+"@npmcli/git@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-2.1.0.tgz#2fbd77e147530247d37f325930d457b3ebe894f6"
+ integrity sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==
+ dependencies:
+ "@npmcli/promise-spawn" "^1.3.2"
+ lru-cache "^6.0.0"
+ mkdirp "^1.0.4"
+ npm-pick-manifest "^6.1.1"
+ promise-inflight "^1.0.1"
+ promise-retry "^2.0.1"
+ semver "^7.3.5"
+ which "^2.0.2"
+
+"@npmcli/installed-package-contents@^1.0.6":
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz#ab7408c6147911b970a8abe261ce512232a3f4fa"
+ integrity sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==
+ dependencies:
+ npm-bundled "^1.1.1"
+ npm-normalize-package-bin "^1.0.1"
+
+"@npmcli/move-file@^1.0.1":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674"
+ integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==
+ dependencies:
+ mkdirp "^1.0.4"
+ rimraf "^3.0.2"
+
+"@npmcli/node-gyp@^1.0.2":
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz#a912e637418ffc5f2db375e93b85837691a43a33"
+ integrity sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA==
+
+"@npmcli/promise-spawn@^1.2.0", "@npmcli/promise-spawn@^1.3.2":
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz#42d4e56a8e9274fba180dabc0aea6e38f29274f5"
+ integrity sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==
+ dependencies:
+ infer-owner "^1.0.4"
+
+"@npmcli/run-script@^1.8.2":
+ version "1.8.6"
+ resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-1.8.6.tgz#18314802a6660b0d4baa4c3afe7f1ad39d8c28b7"
+ integrity sha512-e42bVZnC6VluBZBAFEr3YrdqSspG3bgilyg4nSLBJ7TRGNCzxHa92XAHxQBLYg0BmgwO4b2mf3h/l5EkEWRn3g==
+ dependencies:
+ "@npmcli/node-gyp" "^1.0.2"
+ "@npmcli/promise-spawn" "^1.3.2"
+ node-gyp "^7.1.0"
+ read-package-json-fast "^2.0.1"
+
+"@octokit/auth-token@^2.4.4":
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.5.0.tgz#27c37ea26c205f28443402477ffd261311f21e36"
+ integrity sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==
+ dependencies:
+ "@octokit/types" "^6.0.3"
+
+"@octokit/core@^3.5.1":
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.6.0.tgz#3376cb9f3008d9b3d110370d90e0a1fcd5fe6085"
+ integrity sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==
+ dependencies:
+ "@octokit/auth-token" "^2.4.4"
+ "@octokit/graphql" "^4.5.8"
+ "@octokit/request" "^5.6.3"
+ "@octokit/request-error" "^2.0.5"
+ "@octokit/types" "^6.0.3"
+ before-after-hook "^2.2.0"
+ universal-user-agent "^6.0.0"
+
+"@octokit/endpoint@^6.0.1":
+ version "6.0.12"
+ resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.12.tgz#3b4d47a4b0e79b1027fb8d75d4221928b2d05658"
+ integrity sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==
+ dependencies:
+ "@octokit/types" "^6.0.3"
+ is-plain-object "^5.0.0"
+ universal-user-agent "^6.0.0"
+
+"@octokit/graphql@^4.5.8":
+ version "4.8.0"
+ resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.8.0.tgz#664d9b11c0e12112cbf78e10f49a05959aa22cc3"
+ integrity sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==
+ dependencies:
+ "@octokit/request" "^5.6.0"
+ "@octokit/types" "^6.0.3"
+ universal-user-agent "^6.0.0"
+
+"@octokit/openapi-types@^12.11.0":
+ version "12.11.0"
+ resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-12.11.0.tgz#da5638d64f2b919bca89ce6602d059f1b52d3ef0"
+ integrity sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==
+
+"@octokit/plugin-enterprise-rest@^6.0.1":
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz#e07896739618dab8da7d4077c658003775f95437"
+ integrity sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==
+
+"@octokit/plugin-paginate-rest@^2.16.8":
+ version "2.21.3"
+ resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz#7f12532797775640dbb8224da577da7dc210c87e"
+ integrity sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==
+ dependencies:
+ "@octokit/types" "^6.40.0"
+
+"@octokit/plugin-request-log@^1.0.4":
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85"
+ integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==
+
+"@octokit/plugin-rest-endpoint-methods@^5.12.0":
+ version "5.16.2"
+ resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz#7ee8bf586df97dd6868cf68f641354e908c25342"
+ integrity sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==
+ dependencies:
+ "@octokit/types" "^6.39.0"
+ deprecation "^2.3.1"
+
+"@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.1.0.tgz#9e150357831bfc788d13a4fd4b1913d60c74d677"
+ integrity sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==
+ dependencies:
+ "@octokit/types" "^6.0.3"
+ deprecation "^2.0.0"
+ once "^1.4.0"
+
+"@octokit/request@^5.6.0", "@octokit/request@^5.6.3":
+ version "5.6.3"
+ resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0"
+ integrity sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==
+ dependencies:
+ "@octokit/endpoint" "^6.0.1"
+ "@octokit/request-error" "^2.1.0"
+ "@octokit/types" "^6.16.1"
+ is-plain-object "^5.0.0"
+ node-fetch "^2.6.7"
+ universal-user-agent "^6.0.0"
+
+"@octokit/rest@^18.1.0":
+ version "18.12.0"
+ resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.12.0.tgz#f06bc4952fc87130308d810ca9d00e79f6988881"
+ integrity sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==
+ dependencies:
+ "@octokit/core" "^3.5.1"
+ "@octokit/plugin-paginate-rest" "^2.16.8"
+ "@octokit/plugin-request-log" "^1.0.4"
+ "@octokit/plugin-rest-endpoint-methods" "^5.12.0"
+
+"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.39.0", "@octokit/types@^6.40.0":
+ version "6.41.0"
+ resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.41.0.tgz#e58ef78d78596d2fb7df9c6259802464b5f84a04"
+ integrity sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==
+ dependencies:
+ "@octokit/openapi-types" "^12.11.0"
+
+"@pixi/accessibility@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/accessibility/-/accessibility-6.5.4.tgz#657267dde50e93c3ed5fcb6ba5bd4949ac04c89c"
+ integrity sha512-ZlAzU2V4Nxu+2UHPqgncUgUJlZmzqYz/FugCmgCFpbHGz8uyLEfOL1RaS3rbHzuSl4mLlIqjPldKrD+TY6BPhg==
+
+"@pixi/app@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/app/-/app-6.5.4.tgz#be2379c617f4b78234594a0eafad58294bc4e3ea"
+ integrity sha512-/0tpqAurPQI1rUwYITsnU+mpHgWVlmLp6HrAz4uOlaGj3NCKhb3Cedr39ibT1PslMjmFEd2Xqut7Afz8CH58fw==
+
+"@pixi/canvas-display@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/canvas-display/-/canvas-display-6.5.4.tgz#2aebca749550c5d0d6d35384fa4439566fd142ea"
+ integrity sha512-mhW/cd17XRhdp2iyWayMQDGHANBeEMCpE6Wc0h2oELptjajNESKt5L4zDhJ8zZujQnFrveEPOTlKV1T6Byw70w==
+
+"@pixi/canvas-extract@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/canvas-extract/-/canvas-extract-6.5.4.tgz#8d1f4f6ff6d5568b335331a4fa5eb578456dca1d"
+ integrity sha512-gVAT23askt+WL5iYznjHXD71NbCoy3pzyaZnYckbGl5s9w9h5Z1X+xtbJ1hseQE5YcbwKbx1SdmF+Pp8LMuwDg==
+
+"@pixi/canvas-graphics@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/canvas-graphics/-/canvas-graphics-6.5.4.tgz#495d9b5e5239ae0094e086b7d4216277d6e2133d"
+ integrity sha512-uoepdRKz8aLIMnQVEd9gPw0j8RIxLWLiO1aVEtagrQ4y4XQ0MkFmrFnsM03hZBam/nQDmV6VXAQNwMuCUGBVwg==
+
+"@pixi/canvas-mesh@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/canvas-mesh/-/canvas-mesh-6.5.4.tgz#2982f21b2abbf3576b5780d45377f1f0df028d81"
+ integrity sha512-NGDJ8flUOYvwJrNliP89pG+AfpH4BrD2oo/QvPxLV6o2kcZr5Lk768p6GO+naUnnWCZsDfFoP9zeaJ0Ne5Kqhw==
+
+"@pixi/canvas-particle-container@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/canvas-particle-container/-/canvas-particle-container-6.5.4.tgz#84d56c4d2e0a3bf75b02ea23a1711f29367ba628"
+ integrity sha512-t3bXE4nTlfsStOBSrpPh+rixB9jvkuqbIBlps4w81gciznoE0YFqcCxuy1m1B4098fBH38tm54/UHdlE8iJynw==
+
+"@pixi/canvas-prepare@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/canvas-prepare/-/canvas-prepare-6.5.4.tgz#e179b81f93370393a95d22c401b81e3a97574abe"
+ integrity sha512-UE+dzXrYOnDK61H8nQw4X0xbWuCyJcVsDhjfsI1Uvr3419ASw2/TE1QoaYhKgJxHOKmRXDeBYtysydhHPmk3hw==
+
+"@pixi/canvas-renderer@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/canvas-renderer/-/canvas-renderer-6.5.4.tgz#543a6e0b9d0889b7e86ab5ffaf601a35ab9eb65c"
+ integrity sha512-VuGE1eFUBx1EfjFZEUBiKZqWYSr0JgbTmijQFBlOR05GGDHekSeeyuHC98zCrl+F884bKUOFpf3eIGoRhrFrHA==
+
+"@pixi/canvas-sprite-tiling@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/canvas-sprite-tiling/-/canvas-sprite-tiling-6.5.4.tgz#abfbd63fa1fc83973618202d14cfcce4b56cce86"
+ integrity sha512-EdRCBy+/ABDcnotnrXWegHebJFmiCkw5A+3lodFyWJBdRxzKdqCySopdIj/wtEwgdmbt+haTkTeiLp1udydvcQ==
+
+"@pixi/canvas-sprite@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/canvas-sprite/-/canvas-sprite-6.5.4.tgz#920909c373a69fd17146b54108f68e2568707251"
+ integrity sha512-l3LmALn/07iMWCs22X+rhCS0roppOnE7+rHPsKl+yl89UuVF5dq4unnntfHYHitnbwLFaqjA8+o5J+ck6eHkWQ==
+
+"@pixi/canvas-text@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/canvas-text/-/canvas-text-6.5.4.tgz#cd068855656ce6b293f068a7922d5f374c53239b"
+ integrity sha512-MJCoCFiq83Tg8i+qGJKEhP9QfNS7XHkE548d+y47KeVzLynqDJV4vhhnOBwnpFwFPxiv3Y7f+6PQINIFwhP/BQ==
+
+"@pixi/compressed-textures@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/compressed-textures/-/compressed-textures-6.5.4.tgz#03ff9703b2d4de02a8ef49f712458d31f2750bdd"
+ integrity sha512-9LkytIDUbkHGQCkP1yW4uujzVQCjOOzjtT1WC8/GLhqBal8TUeKEybqiRyT2bpb/ssEK3dQ2Sg2UANtKOtXJPg==
+
+"@pixi/constants@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/constants/-/constants-6.5.4.tgz#3037c4d7d149390b75078e16bab99860ceb78534"
+ integrity sha512-u1cmuMeDj9tIDXiiLYhA858rxGZag02WOjZfL1SYtqCxuj1rOLjGL3ttW5jiaiHFtET4HLjdmqhA77o0FWDC/Q==
+
+"@pixi/core@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/core/-/core-6.5.4.tgz#a0f7a585013d56e2dac7badd0242c758cd82bcd9"
+ integrity sha512-+85CHrBI37n5wXQ6rtYx9gaEVkj+m+z54GKHtiz1xLi0kjuyI728vTb3+wKVDYaA5+Q/FLQ5LAplWsllQNJ2Rw==
+ dependencies:
+ "@types/offscreencanvas" "^2019.6.4"
+
+"@pixi/display@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/display/-/display-6.5.4.tgz#e74d970d1798d8abd89b5f258849c91356691153"
+ integrity sha512-2aEK/BfCq7VE8qlYnI2i3v1HDhLM0jH2xEKsP4GFUCGszI834CnHQDfn1XySfynOYVlytM4J8D0wNG4vWmrfnQ==
+
+"@pixi/events@^6.2.0":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/events/-/events-6.5.4.tgz#b7682f9b61c10292fc42e2cd3092052f0d9118e8"
+ integrity sha512-OUYAmd1PlXl98+FYD0zhFBJxeJMZykkuzYaJma77ClkEsl6baiujThVQFkESFQpXpuzW+VcSUFBeklNheJ1FFg==
+
+"@pixi/extensions@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/extensions/-/extensions-6.5.4.tgz#de55eae9a23c2eeafa364bef64cb838a2d120990"
+ integrity sha512-I9XLxan/CvYfJPzCoZJrIEWtG9KGGMHs4y9SpVggYNcU6IOtf3N6xA0LvG1nxtbE1+CNRtw+9DfZ0dypytU1XQ==
+
+"@pixi/extract@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/extract/-/extract-6.5.4.tgz#ac49de53f6639c4b4e904f306a3a0a5583ee47d4"
+ integrity sha512-9Lk6UuPqQcQGgiCsO09M7SFAoeuGz5dLBw5Z7T8ZNlOabKnL25IhzWjQ9MdeOrh6CU43TH7/2Ng0oMhsHHW5aw==
+
+"@pixi/filter-alpha@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/filter-alpha/-/filter-alpha-6.5.4.tgz#67a452abd723f20995d35c811ec10510c450d90f"
+ integrity sha512-8SCJm/D4muQvIE9CQZzBusozTIocE05+uzf/YNazH3Hbhu/RUNk/m/dyjR4Xa+4GcvdV7hJBtM+CGDxAAEHfaw==
+
+"@pixi/filter-blur@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/filter-blur/-/filter-blur-6.5.4.tgz#c4603fa0be76d9920e09d954dda70c2d3fc47ee2"
+ integrity sha512-gaRz9Z/XxSkGXdCs6aJqJsaACp1o7rxCEqUFQUAh/DfhzIwI91IPQjnOuAQbZu51OLn8z8FtRcNcBggfDyCIQA==
+
+"@pixi/filter-color-matrix@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/filter-color-matrix/-/filter-color-matrix-6.5.4.tgz#ff36592bba1f1f9721db74f5a90f88a069efc41e"
+ integrity sha512-xol2nxjlxB9JPxPKoj0FkmdBiLgBzg4Lp7ZeCNvThoOTMWbZ1R9uY2cg5xJ3E+VyXdyNqXPBisHc0FvhV3MbYw==
+
+"@pixi/filter-displacement@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/filter-displacement/-/filter-displacement-6.5.4.tgz#daadb98cdabf1875b943888a2575e6964922976b"
+ integrity sha512-u91HFap9fOcNkUQjg/xJLHgOVNlnLcHaa/Y6PmNH8dl8QTTxpinmxUDIre7GInB1m4q0LhmKaq42wShM57G6Wg==
+
+"@pixi/filter-fxaa@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/filter-fxaa/-/filter-fxaa-6.5.4.tgz#7caa05496d0ef2b1e99b7e9a7df4b26629bb058b"
+ integrity sha512-Ep16Ms75fc4Da5c0ltlQi59yBPk8EtMIOYt/r8nPOYQwNHdkgMOfezWC25ebN8sjWgMDRFSHMan6zwvawALf4w==
+
+"@pixi/filter-noise@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/filter-noise/-/filter-noise-6.5.4.tgz#9428160d0512e286c53574185b23a042d3c17839"
+ integrity sha512-CvDJiKRLZE7h9n01B77hOWGB41DGKskAk5lGSPDbrtmCf5zz5QFatjzeNbSZwcHnvHBSmKhoAPdk72bpkFxrew==
+
+"@pixi/graphics@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/graphics/-/graphics-6.5.4.tgz#f75af8d213572d604822a6f7701397e6916cc071"
+ integrity sha512-9ekmienQNocW2FqLSkItj2YAyBStqXimAxu1jXehrhr0aB0Sln9imf6GemK/GJUaXsMmXUto/3EVFX2RuQdO3g==
+
+"@pixi/interaction@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/interaction/-/interaction-6.5.4.tgz#fea72d0e824446906d331c0f96e20de2ffe2a44b"
+ integrity sha512-Csdh72ftW/HJ7hapZsMLhJYeGe+epu+Zfr8BX63X3pv3kwr7FL/68WvpmZNZyg0H4VIzseXlNFv/hFCWkfeg/A==
+
+"@pixi/loaders@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/loaders/-/loaders-6.5.4.tgz#ef853d52153fd061df1fd1af1f73f254773a85ce"
+ integrity sha512-U+z3+Ky/AgCoayKe+CR+3VZXc0dJ08hc33FbEhuJB6qTpSlz2LcGQUksvHG5nyKpEW+zLY0vQS4yrEaoAPunJg==
+
+"@pixi/math@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/math/-/math-6.5.4.tgz#4cbda378ecba9b08c4a0aad49786fcdd4242df8d"
+ integrity sha512-+S9AaLGwgIlDwj7J2ny2oYL0BR9Bie8HOOLQ1kJKH6N82s5RKTCtckjC0v1+D++tyPRcOos6lus+FWHTb/h/BQ==
+
+"@pixi/mesh-extras@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/mesh-extras/-/mesh-extras-6.5.4.tgz#298ab945e675ea91853476b9d0fa911270c7fca4"
+ integrity sha512-uowBlNiku213yy/jHDYrRr2Feq8BPqUhTbPHsXV+Nub87cdyopzfKVjiPJjUrtvmk8xFbJU/wFhoZbAgP51otA==
+
+"@pixi/mesh@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/mesh/-/mesh-6.5.4.tgz#54137daa8e59ea1fe463ad0688f3771aba7f4328"
+ integrity sha512-JxtMHJWeO0QfSMrlwA9lvTkUS3JDVlELQMDzv1L/POWvlm2DEKHbDapCFTe3SLoHTuzD7d2Ioxw6WL0Ww1rKCA==
+
+"@pixi/mixin-cache-as-bitmap@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/mixin-cache-as-bitmap/-/mixin-cache-as-bitmap-6.5.4.tgz#2d35e1075c6d20e477006d5ac8e1dfc39e5c67ac"
+ integrity sha512-gT0hlk5OvUpMxOLb39UIhV6FjiqYbCYHo2kVVccUIlJV5TX9ifso9MIPWJoanpjDXQXv6pinXb3v7Nn0WFgLjA==
+
+"@pixi/mixin-get-child-by-name@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/mixin-get-child-by-name/-/mixin-get-child-by-name-6.5.4.tgz#8adfdf21fe624e475ca51e0a4a0b23b562c3eb66"
+ integrity sha512-6aP+06PPSiYMKqxlbozBgNQrb00/9ssI87OdW/TCU4p2I1WpYBMD0npCjlL4sS5cWpqHnklsaT8knPBMIgTVSw==
+
+"@pixi/mixin-get-global-position@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/mixin-get-global-position/-/mixin-get-global-position-6.5.4.tgz#2e06f92f193924beed5e9cce320529d788e3f486"
+ integrity sha512-7BLaGTSh+dKka4r4BQC7Br//YfitbWUQIIBSC1uW/pCiLzRFry193OEiIpvRVp9/mk117bxb2C+YqxVbO8ZlEQ==
+
+"@pixi/particle-container@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/particle-container/-/particle-container-6.5.4.tgz#438ccf213a3d154418ccce1676ad9c1942b067bc"
+ integrity sha512-w94ln+syQhRSiZxI90dDYraGCa3UMJ0qiwNMlRcPj3yw6pw/5ZnR5sOFMW2oTZBCagd59Z4cpoS1mdP1wptytA==
+
+"@pixi/polyfill@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/polyfill/-/polyfill-6.5.4.tgz#8e27393eed86c91cd660a8052cbd25becf66c941"
+ integrity sha512-YSJIlQngSEi6J8nMvjA1IzHnrr1h3JfuA0OT5eFkxoFBBWTPnfmJaDLpaULmpTwK3118sndDXLIr4iXF3tYvgg==
+ dependencies:
+ object-assign "^4.1.1"
+ promise-polyfill "^8.2.0"
+
+"@pixi/prepare@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/prepare/-/prepare-6.5.4.tgz#c6ec44d3b762055c27e0af9b6b7bac0e8ad34d34"
+ integrity sha512-Nb8432o5WF5/3h0P3dSW61KlQpElYMn8MwBfDwH3Hy5b0flc/BfKKq9GUheMaznPzPQ+3vbvJr6KhKWjLhZq7A==
+
+"@pixi/runner@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/runner/-/runner-6.5.4.tgz#be1e615e8694fedefe4ff2e07c0614f2c084365c"
+ integrity sha512-DRdo9z+YR4C5BIiYJ11e8/p9gGWjXMZglFQZYmhi1cGpjljMnuROJGVgSWqsD7GhJAu60Xp9+nKdPIRPPdaG7Q==
+
+"@pixi/settings@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/settings/-/settings-6.5.4.tgz#3ff523bc646754ac311b35c1d7b4f789f02d54a0"
+ integrity sha512-RlW8xZU0ViaVM36s/3rwGI6RWo2YgtlQMwutH16vTmtgWxesBp3C1TS0TcWdNf2DxqRpcKldexJr636vKlrKUA==
+
+"@pixi/sprite-animated@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/sprite-animated/-/sprite-animated-6.5.4.tgz#a682f4ecc2aa8042f07747fa53f3db1fb180f618"
+ integrity sha512-vqUuiyIExT8pU2PRCtpGrC4GwAkl83P+5yNnX4vCFf409LsV4zfuq5/nCLPlM75t4kEER8lim+QxfqoMQR6VOQ==
+
+"@pixi/sprite-tiling@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/sprite-tiling/-/sprite-tiling-6.5.4.tgz#bacdededb1732c4a677b762b6c94828fa34aaed5"
+ integrity sha512-6JG3dc6x1tMAZ2cvf03YkgifGSvXR3+//oiQrLljQ81wS2+Ba8yCC7unnFCH6JfBoSkPkgJI40ZAnCJ7/Vghiw==
+
+"@pixi/sprite@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/sprite/-/sprite-6.5.4.tgz#646d47a65683d5ecc8b2e76b476e910f27dace0f"
+ integrity sha512-hqPJD9zb1QH4rbfTJejia6OvQdlgx2vUG/pBx6fslMXx+DhrdLuw8aLVYnmClP5V+CQaNv8ZVWrkrPyIurtYYA==
+
+"@pixi/spritesheet@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/spritesheet/-/spritesheet-6.5.4.tgz#f7b7c22355ab1ce4712045dcbdc4913f48e2319e"
+ integrity sha512-RzS+l/9MOO+7N+n+tONQyCgJtUF3ypOfeshBvswCLUShBtlK0p8IdOepZhm6UYFqYRQIhodH2aJXFslIFVZxeg==
+
+"@pixi/text-bitmap@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/text-bitmap/-/text-bitmap-6.5.4.tgz#e667d29503eefd88541925022118f06b02544736"
+ integrity sha512-cHmtLJ9mv3sSOqcCGTP6ArlPumhov1rtzChhffyBRXTWSOiXNVDIjtSXmcRjgmnFmmJX+umDj/j3z2WNVak52Q==
+
+"@pixi/text@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/text/-/text-6.5.4.tgz#682a2e14b55733e0a731fb5ebbad42bde44366ed"
+ integrity sha512-dihHc6chK1HNCQKSW7KIGOpz6q4GHkqyq2TU+htpTDaaU9ynd5/SGrz1DARWyjE3X3GgcVI5C218JAtHg45sEA==
+
+"@pixi/ticker@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/ticker/-/ticker-6.5.4.tgz#326171aa1c1cd38413b1de914564265ae49fc15f"
+ integrity sha512-Q+djAwtJ7m4n7B9Lc239WfVHr/9u/bw692DwF3btYJzYFg1/XdVvorvb1kiNI+s4DeQHRYIha91tXGImVBtgVQ==
+
+"@pixi/unsafe-eval@^6.2.0":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/unsafe-eval/-/unsafe-eval-6.5.4.tgz#443fe13341df573c31e008580a1c97acda356ba7"
+ integrity sha512-tp86c/U/qhkh1Ced11xEB40qm+0dFLXiqGJj5tqmTy3XrtzEphx+BY7PbMtNZkMD2N60KSwP+/sHtZDhmVwlAw==
+
+"@pixi/utils@6.5.4":
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/@pixi/utils/-/utils-6.5.4.tgz#04aedede4709b4d198f1bf4b8341bb88591b1e90"
+ integrity sha512-jdnS3aoEhAYoNF2P4njSFPwVc+/4X0F3/5vnNtqCUeDJcz6erNRzO6OEiSDPQMTAt/q5kKpxvtCKGaQmkwlhVA==
+ dependencies:
+ "@types/earcut" "^2.1.0"
+ earcut "^2.2.4"
+ eventemitter3 "^3.1.0"
+ url "^0.11.0"
+
+"@popperjs/core@^2.11.0":
+ version "2.11.8"
+ resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f"
+ integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
+
+"@sideway/address@^4.1.3":
+ version "4.1.4"
+ resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0"
+ integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==
+ dependencies:
+ "@hapi/hoek" "^9.0.0"
+
+"@sideway/formula@^3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c"
+ integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==
+
+"@sideway/pinpoint@^2.0.0":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
+ integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
+
+"@sindresorhus/is@^0.14.0":
+ version "0.14.0"
+ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
+ integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
+
+"@socket.io/component-emitter@~3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553"
+ integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==
+
+"@stylistic/eslint-plugin-js@2.1.0", "@stylistic/eslint-plugin-js@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.1.0.tgz#3c4053c12bc6cc344f8ca979bb4399cda386e7a5"
+ integrity sha512-gdXUjGNSsnY6nPyqxu6lmDTtVrwCOjun4x8PUn0x04d5ucLI74N3MT1Q0UhdcOR9No3bo5PGDyBgXK+KmD787A==
+ dependencies:
+ "@types/eslint" "^8.56.10"
+ acorn "^8.11.3"
+ eslint-visitor-keys "^4.0.0"
+ espree "^10.0.1"
+
+"@stylistic/eslint-plugin-jsx@2.1.0":
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-2.1.0.tgz#ce59d90bc47bc7ecc43574440b19b69d3b0dc5f1"
+ integrity sha512-mMD7S+IndZo2vxmwpHVTCwx2O1VdtE5tmpeNwgaEcXODzWV1WTWpnsc/PECQKIr/mkLPFWiSIqcuYNhQ/3l6AQ==
+ dependencies:
+ "@stylistic/eslint-plugin-js" "^2.1.0"
+ "@types/eslint" "^8.56.10"
+ estraverse "^5.3.0"
+ picomatch "^4.0.2"
+
+"@stylistic/eslint-plugin-plus@2.1.0":
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-2.1.0.tgz#c02890685df3a4e5b9ff9ee113377bb237401695"
+ integrity sha512-S5QAlgYXESJaSBFhBSBLZy9o36gXrXQwWSt6QkO+F0SrT9vpV5JF/VKoh+ojO7tHzd8Ckmyouq02TT9Sv2B0zQ==
+ dependencies:
+ "@types/eslint" "^8.56.10"
+ "@typescript-eslint/utils" "^7.8.0"
+
+"@stylistic/eslint-plugin-ts@2.1.0":
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-2.1.0.tgz#74083f74aacea19e7bc4509dafc56da7c4c40667"
+ integrity sha512-2ioFibufHYBALx2TBrU4KXovCkN8qCqcb9yIHc0fyOfTaO5jw4d56WW7YRcF3Zgde6qFyXwAN6z/+w4pnmos1g==
+ dependencies:
+ "@stylistic/eslint-plugin-js" "2.1.0"
+ "@types/eslint" "^8.56.10"
+ "@typescript-eslint/utils" "^7.8.0"
+
+"@stylistic/eslint-plugin@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/@stylistic/eslint-plugin/-/eslint-plugin-2.1.0.tgz#61b73f7d4f6786517224aa3dee78c9ace5ca7d76"
+ integrity sha512-cBBowKP2u/+uE5CzgH5w8pE9VKqcM7BXdIDPIbGt2rmLJGnA6MJPr9vYGaqgMoJFs7R/FzsMQerMvvEP40g2uw==
+ dependencies:
+ "@stylistic/eslint-plugin-js" "2.1.0"
+ "@stylistic/eslint-plugin-jsx" "2.1.0"
+ "@stylistic/eslint-plugin-plus" "2.1.0"
+ "@stylistic/eslint-plugin-ts" "2.1.0"
+ "@types/eslint" "^8.56.10"
+
+"@szmarczak/http-timer@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421"
+ integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==
+ dependencies:
+ defer-to-connect "^1.0.1"
+
+"@tailwindcss/postcss7-compat@^2.0.4", "tailwindcss@npm:@tailwindcss/postcss7-compat":
+ version "2.2.17"
+ resolved "https://registry.yarnpkg.com/@tailwindcss/postcss7-compat/-/postcss7-compat-2.2.17.tgz#dc78f3880a2af84163150ff426a39e42b9ae8922"
+ integrity sha512-3h2svqQAqYHxRZ1KjsJjZOVTQ04m29LjfrLjXyZZEJuvUuJN+BCIF9GI8vhE1s0plS0mogd6E6YLg6mu4Wv/Vw==
+ dependencies:
+ arg "^5.0.1"
+ autoprefixer "^9"
+ bytes "^3.0.0"
+ chalk "^4.1.2"
+ chokidar "^3.5.2"
+ color "^4.0.1"
+ cosmiconfig "^7.0.1"
+ detective "^5.2.0"
+ didyoumean "^1.2.2"
+ dlv "^1.1.3"
+ fast-glob "^3.2.7"
+ fs-extra "^10.0.0"
+ glob-parent "^6.0.1"
+ html-tags "^3.1.0"
+ is-color-stop "^1.1.0"
+ is-glob "^4.0.1"
+ lodash "^4.17.21"
+ lodash.topath "^4.5.2"
+ modern-normalize "^1.1.0"
+ node-emoji "^1.11.0"
+ normalize-path "^3.0.0"
+ object-hash "^2.2.0"
+ postcss "^7"
+ postcss-functions "^3"
+ postcss-js "^2"
+ postcss-load-config "^3.1.0"
+ postcss-nested "^4"
+ postcss-selector-parser "^6.0.6"
+ postcss-value-parser "^4.1.0"
+ pretty-hrtime "^1.0.3"
+ purgecss "^4.0.3"
+ quick-lru "^5.1.1"
+ reduce-css-calc "^2.1.8"
+ resolve "^1.20.0"
+ tmp "^0.2.1"
+
+"@tootallnate/once@1":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
+ integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
+
+"@types/body-parser@*":
+ version "1.19.5"
+ resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4"
+ integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==
+ dependencies:
+ "@types/connect" "*"
+ "@types/node" "*"
+
+"@types/bonjour@^3.5.9":
+ version "3.5.13"
+ resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.13.tgz#adf90ce1a105e81dd1f9c61fdc5afda1bfb92956"
+ integrity sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==
+ dependencies:
+ "@types/node" "*"
+
+"@types/chrome@^0.0.139":
+ version "0.0.139"
+ resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.139.tgz#225fb926029d92e01ad24b5004c3cfed64376605"
+ integrity sha512-YZDKFlSVGFp4zldJlO+PUpxMH8N9vLke0fD6K9PA+TzXxPXu8LBLo5X2dzlOs2N/n+uMdI1lw7OPT1Emop10lQ==
+ dependencies:
+ "@types/filesystem" "*"
+ "@types/har-format" "*"
+
+"@types/connect-history-api-fallback@^1.3.5":
+ version "1.5.4"
+ resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz#7de71645a103056b48ac3ce07b3520b819c1d5b3"
+ integrity sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==
+ dependencies:
+ "@types/express-serve-static-core" "*"
+ "@types/node" "*"
+
+"@types/connect@*":
+ version "3.4.38"
+ resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858"
+ integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==
+ dependencies:
+ "@types/node" "*"
+
+"@types/cookie@^0.4.1":
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d"
+ integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==
+
+"@types/cors@^2.8.12":
+ version "2.8.12"
+ resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080"
+ integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==
+
+"@types/earcut@^2.1.0":
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/@types/earcut/-/earcut-2.1.1.tgz#573a0af609f17005c751f6f4ffec49cfe358ea51"
+ integrity sha512-w8oigUCDjElRHRRrMvn/spybSMyX8MTkKA5Dv+tS1IE/TgmNZPqUYtvYBXGY8cieSE66gm+szeK+bnbxC2xHTQ==
+
+"@types/eslint-scope@^3.7.3":
+ version "3.7.4"
+ resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16"
+ integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==
+ dependencies:
+ "@types/eslint" "*"
+ "@types/estree" "*"
+
+"@types/eslint@*":
+ version "8.4.6"
+ resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.6.tgz#7976f054c1bccfcf514bff0564c0c41df5c08207"
+ integrity sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==
+ dependencies:
+ "@types/estree" "*"
+ "@types/json-schema" "*"
+
+"@types/eslint@^8.56.10", "@types/eslint@^8.56.5":
+ version "8.56.10"
+ resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.10.tgz#eb2370a73bf04a901eeba8f22595c7ee0f7eb58d"
+ integrity sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==
+ dependencies:
+ "@types/estree" "*"
+ "@types/json-schema" "*"
+
+"@types/estree@*":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2"
+ integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==
+
+"@types/estree@^1.0.5":
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
+ integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
+
+"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33":
+ version "4.17.43"
+ resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz#10d8444be560cb789c4735aea5eac6e5af45df54"
+ integrity sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==
+ dependencies:
+ "@types/node" "*"
+ "@types/qs" "*"
+ "@types/range-parser" "*"
+ "@types/send" "*"
+
+"@types/express@*", "@types/express@^4.17.13":
+ version "4.17.21"
+ resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d"
+ integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==
+ dependencies:
+ "@types/body-parser" "*"
+ "@types/express-serve-static-core" "^4.17.33"
+ "@types/qs" "*"
+ "@types/serve-static" "*"
+
+"@types/filesystem@*":
+ version "0.0.32"
+ resolved "https://registry.yarnpkg.com/@types/filesystem/-/filesystem-0.0.32.tgz#307df7cc084a2293c3c1a31151b178063e0a8edf"
+ integrity sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ==
+ dependencies:
+ "@types/filewriter" "*"
+
+"@types/filewriter@*":
+ version "0.0.29"
+ resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.29.tgz#a48795ecadf957f6c0d10e0c34af86c098fa5bee"
+ integrity sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ==
+
+"@types/har-format@*":
+ version "1.2.9"
+ resolved "https://registry.yarnpkg.com/@types/har-format/-/har-format-1.2.9.tgz#b9b3a9bfc33a078e7d898a00b09662910577f4a4"
+ integrity sha512-rffW6MhQ9yoa75bdNi+rjZBAvu2HhehWJXlhuWXnWdENeuKe82wUgAwxYOb7KRKKmxYN+D/iRKd2NDQMLqlUmg==
+
+"@types/http-errors@*":
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f"
+ integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==
+
+"@types/http-proxy@^1.17.8":
+ version "1.17.9"
+ resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a"
+ integrity sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==
+ dependencies:
+ "@types/node" "*"
+
+"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
+ version "7.0.11"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
+ integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
+
+"@types/mdast@^3.0.0":
+ version "3.0.15"
+ resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5"
+ integrity sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==
+ dependencies:
+ "@types/unist" "^2"
+
+"@types/mime@*":
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.4.tgz#2198ac274de6017b44d941e00261d5bc6a0e0a45"
+ integrity sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==
+
+"@types/mime@^1":
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690"
+ integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==
+
+"@types/minimatch@^3.0.3":
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
+ integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==
+
+"@types/minimist@^1.2.0":
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c"
+ integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==
+
+"@types/node-forge@^1.3.0":
+ version "1.3.11"
+ resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da"
+ integrity sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==
+ dependencies:
+ "@types/node" "*"
+
+"@types/node@*", "@types/node@>=10.0.0":
+ version "18.7.19"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.19.tgz#ad83aa9b7af470fab7e0f562be87e97dc8ffe08e"
+ integrity sha512-Sq1itGUKUX1ap7GgZlrzdBydjbsJL/NSQt/4wkAxUJ7/OS5c2WkoN6WSpWc2Yc5wtKMZOUA0VCs/j2XJadN3HA==
+
+"@types/node@^16.11.26":
+ version "16.11.62"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.62.tgz#bab2e6208531321d147eda20c38e389548cd5ffc"
+ integrity sha512-K/ggecSdwAAy2NUW4WKmF4Rc03GKbsfP+k326UWgckoS+Rzd2PaWbjk76dSmqdLQvLTJAO9axiTUJ6488mFsYQ==
+
+"@types/node@^20.11.16":
+ version "20.11.16"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.16.tgz#4411f79411514eb8e2926f036c86c9f0e4ec6708"
+ integrity sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==
+ dependencies:
+ undici-types "~5.26.4"
+
+"@types/normalize-package-data@^2.4.0":
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
+ integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==
+
+"@types/offscreencanvas@^2019.6.4":
+ version "2019.7.0"
+ resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz#e4a932069db47bb3eabeb0b305502d01586fa90d"
+ integrity sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==
+
+"@types/parse-json@^4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
+ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
+
+"@types/qs@*":
+ version "6.9.11"
+ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.11.tgz#208d8a30bc507bd82e03ada29e4732ea46a6bbda"
+ integrity sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==
+
+"@types/range-parser@*":
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb"
+ integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==
+
+"@types/retry@0.12.0":
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
+ integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==
+
+"@types/send@*":
+ version "0.17.4"
+ resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a"
+ integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==
+ dependencies:
+ "@types/mime" "^1"
+ "@types/node" "*"
+
+"@types/serve-index@^1.9.1":
+ version "1.9.4"
+ resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.4.tgz#e6ae13d5053cb06ed36392110b4f9a49ac4ec898"
+ integrity sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==
+ dependencies:
+ "@types/express" "*"
+
+"@types/serve-static@*", "@types/serve-static@^1.13.10":
+ version "1.15.5"
+ resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.5.tgz#15e67500ec40789a1e8c9defc2d32a896f05b033"
+ integrity sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==
+ dependencies:
+ "@types/http-errors" "*"
+ "@types/mime" "*"
+ "@types/node" "*"
+
+"@types/sockjs@^0.3.33":
+ version "0.3.36"
+ resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535"
+ integrity sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==
+ dependencies:
+ "@types/node" "*"
+
+"@types/speakingurl@^13.0.3":
+ version "13.0.3"
+ resolved "https://registry.yarnpkg.com/@types/speakingurl/-/speakingurl-13.0.3.tgz#cbfe3d0182c7af92ebac7e587bb9228472e05133"
+ integrity sha512-nBHZAaNTEw1YG3ROL7HtTp7HjW8HD7DuFYbWoonUKTZHj7eyOt4vPzyMcc3+xgWNv7xi2rziaiBXHIq6wBeyrw==
+
+"@types/unist@^2", "@types/unist@^2.0.2":
+ version "2.0.10"
+ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc"
+ integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==
+
+"@types/web-bluetooth@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz#f066abfcd1cbe66267cdbbf0de010d8a41b41597"
+ integrity sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==
+
+"@types/webpack-env@^1.15.1":
+ version "1.18.0"
+ resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.18.0.tgz#ed6ecaa8e5ed5dfe8b2b3d00181702c9925f13fb"
+ integrity sha512-56/MAlX5WMsPVbOg7tAxnYvNYMMWr/QJiIp6BxVSW3JJXUVzzOn64qW8TzQyMSqSUFM2+PVI4aUHcHOzIz/1tg==
+
+"@types/ws@^8.5.5":
+ version "8.5.10"
+ resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787"
+ integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==
+ dependencies:
+ "@types/node" "*"
+
+"@types/yauzl@^2.9.1":
+ version "2.10.0"
+ resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599"
+ integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==
+ dependencies:
+ "@types/node" "*"
+
+"@typescript-eslint/eslint-plugin@^7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.11.0.tgz#f90f0914657ead08e1c75f66939c926edeab42dd"
+ integrity sha512-P+qEahbgeHW4JQ/87FuItjBj8O3MYv5gELDzr8QaQ7fsll1gSMTYb6j87MYyxwf3DtD7uGFB9ShwgmCJB5KmaQ==
+ dependencies:
+ "@eslint-community/regexpp" "^4.10.0"
+ "@typescript-eslint/scope-manager" "7.11.0"
+ "@typescript-eslint/type-utils" "7.11.0"
+ "@typescript-eslint/utils" "7.11.0"
+ "@typescript-eslint/visitor-keys" "7.11.0"
+ graphemer "^1.4.0"
+ ignore "^5.3.1"
+ natural-compare "^1.4.0"
+ ts-api-utils "^1.3.0"
+
+"@typescript-eslint/parser@^7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.11.0.tgz#525ad8bee54a8f015f134edd241d91b84ab64839"
+ integrity sha512-yimw99teuaXVWsBcPO1Ais02kwJ1jmNA1KxE7ng0aT7ndr1pT1wqj0OJnsYVGKKlc4QJai86l/025L6z8CljOg==
+ dependencies:
+ "@typescript-eslint/scope-manager" "7.11.0"
+ "@typescript-eslint/types" "7.11.0"
+ "@typescript-eslint/typescript-estree" "7.11.0"
+ "@typescript-eslint/visitor-keys" "7.11.0"
+ debug "^4.3.4"
+
+"@typescript-eslint/scope-manager@7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz#cf5619b01de62a226a59add15a02bde457335d1d"
+ integrity sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw==
+ dependencies:
+ "@typescript-eslint/types" "7.11.0"
+ "@typescript-eslint/visitor-keys" "7.11.0"
+
+"@typescript-eslint/type-utils@7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.11.0.tgz#ac216697d649084fedf4a910347b9642bd0ff099"
+ integrity sha512-WmppUEgYy+y1NTseNMJ6mCFxt03/7jTOy08bcg7bxJJdsM4nuhnchyBbE8vryveaJUf62noH7LodPSo5Z0WUCg==
+ dependencies:
+ "@typescript-eslint/typescript-estree" "7.11.0"
+ "@typescript-eslint/utils" "7.11.0"
+ debug "^4.3.4"
+ ts-api-utils "^1.3.0"
+
+"@typescript-eslint/types@7.11.0", "@typescript-eslint/types@^7.2.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.11.0.tgz#5e9702a5e8b424b7fc690e338d359939257d6722"
+ integrity sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==
+
+"@typescript-eslint/typescript-estree@7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.11.0.tgz#7cbc569bc7336c3a494ceaf8204fdee5d5dbb7fa"
+ integrity sha512-cxkhZ2C/iyi3/6U9EPc5y+a6csqHItndvN/CzbNXTNrsC3/ASoYQZEt9uMaEp+xFNjasqQyszp5TumAVKKvJeQ==
+ dependencies:
+ "@typescript-eslint/types" "7.11.0"
+ "@typescript-eslint/visitor-keys" "7.11.0"
+ debug "^4.3.4"
+ globby "^11.1.0"
+ is-glob "^4.0.3"
+ minimatch "^9.0.4"
+ semver "^7.6.0"
+ ts-api-utils "^1.3.0"
+
+"@typescript-eslint/utils@7.11.0", "@typescript-eslint/utils@^6.13.0 || ^7.0.0", "@typescript-eslint/utils@^7.4.0", "@typescript-eslint/utils@^7.7.1", "@typescript-eslint/utils@^7.8.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.11.0.tgz#524f047f2209959424c3ef689b0d83b3bc09919c"
+ integrity sha512-xlAWwPleNRHwF37AhrZurOxA1wyXowW4PqVXZVUNCLjB48CqdPJoJWkrpH2nij9Q3Lb7rtWindtoXwxjxlKKCA==
+ dependencies:
+ "@eslint-community/eslint-utils" "^4.4.0"
+ "@typescript-eslint/scope-manager" "7.11.0"
+ "@typescript-eslint/types" "7.11.0"
+ "@typescript-eslint/typescript-estree" "7.11.0"
+
+"@typescript-eslint/visitor-keys@7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz#2c50cd292e67645eec05ac0830757071b4a4d597"
+ integrity sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ==
+ dependencies:
+ "@typescript-eslint/types" "7.11.0"
+ eslint-visitor-keys "^3.4.3"
+
+"@vitejs/plugin-vue@^2.3.2":
+ version "2.3.4"
+ resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-2.3.4.tgz#966a6279060eb2d9d1a02ea1a331af071afdcf9e"
+ integrity sha512-IfFNbtkbIm36O9KB8QodlwwYvTEsJb4Lll4c2IwB3VHc2gie2mSPtSzL0eYay7X2jd/2WX02FjSGTWR6OPr/zg==
+
+"@vue/compiler-core@3.2.39":
+ version "3.2.39"
+ resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.39.tgz#0d77e635f4bdb918326669155a2dc977c053943e"
+ integrity sha512-mf/36OWXqWn0wsC40nwRRGheR/qoID+lZXbIuLnr4/AngM0ov8Xvv8GHunC0rKRIkh60bTqydlqTeBo49rlbqw==
+ dependencies:
+ "@babel/parser" "^7.16.4"
+ "@vue/shared" "3.2.39"
+ estree-walker "^2.0.2"
+ source-map "^0.6.1"
+
+"@vue/compiler-core@3.3.4":
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.3.4.tgz#7fbf591c1c19e1acd28ffd284526e98b4f581128"
+ integrity sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==
+ dependencies:
+ "@babel/parser" "^7.21.3"
+ "@vue/shared" "3.3.4"
+ estree-walker "^2.0.2"
+ source-map-js "^1.0.2"
+
+"@vue/compiler-dom@3.2.39":
+ version "3.2.39"
+ resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.39.tgz#bd69d35c1a48fe2cea4ab9e96d2a3a735d146fdf"
+ integrity sha512-HMFI25Be1C8vLEEv1hgEO1dWwG9QQ8LTTPmCkblVJY/O3OvWx6r1+zsox5mKPMGvqYEZa6l8j+xgOfUspgo7hw==
+ dependencies:
+ "@vue/compiler-core" "3.2.39"
+ "@vue/shared" "3.2.39"
+
+"@vue/compiler-dom@3.3.4":
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz#f56e09b5f4d7dc350f981784de9713d823341151"
+ integrity sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==
+ dependencies:
+ "@vue/compiler-core" "3.3.4"
+ "@vue/shared" "3.3.4"
+
+"@vue/compiler-sfc@2.7.10":
+ version "2.7.10"
+ resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-2.7.10.tgz#3fe08e780053a3bbf41328c65ae5dfdee0385206"
+ integrity sha512-55Shns6WPxlYsz4WX7q9ZJBL77sKE1ZAYNYStLs6GbhIOMrNtjMvzcob6gu3cGlfpCR4bT7NXgyJ3tly2+Hx8Q==
+ dependencies:
+ "@babel/parser" "^7.18.4"
+ postcss "^8.4.14"
+ source-map "^0.6.1"
+
+"@vue/compiler-sfc@3.2.39":
+ version "3.2.39"
+ resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.39.tgz#8fe29990f672805b7c5a2ecfa5b05e681c862ea2"
+ integrity sha512-fqAQgFs1/BxTUZkd0Vakn3teKUt//J3c420BgnYgEOoVdTwYpBTSXCMJ88GOBCylmUBbtquGPli9tVs7LzsWIA==
+ dependencies:
+ "@babel/parser" "^7.16.4"
+ "@vue/compiler-core" "3.2.39"
+ "@vue/compiler-dom" "3.2.39"
+ "@vue/compiler-ssr" "3.2.39"
+ "@vue/reactivity-transform" "3.2.39"
+ "@vue/shared" "3.2.39"
+ estree-walker "^2.0.2"
+ magic-string "^0.25.7"
+ postcss "^8.1.10"
+ source-map "^0.6.1"
+
+"@vue/compiler-sfc@3.3.4", "@vue/compiler-sfc@^3.3.4":
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz#b19d942c71938893535b46226d602720593001df"
+ integrity sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==
+ dependencies:
+ "@babel/parser" "^7.20.15"
+ "@vue/compiler-core" "3.3.4"
+ "@vue/compiler-dom" "3.3.4"
+ "@vue/compiler-ssr" "3.3.4"
+ "@vue/reactivity-transform" "3.3.4"
+ "@vue/shared" "3.3.4"
+ estree-walker "^2.0.2"
+ magic-string "^0.30.0"
+ postcss "^8.1.10"
+ source-map-js "^1.0.2"
+
+"@vue/compiler-ssr@3.2.39":
+ version "3.2.39"
+ resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.39.tgz#4f3bfb535cb98b764bee45e078700e03ccc60633"
+ integrity sha512-EoGCJ6lincKOZGW+0Ky4WOKsSmqL7hp1ZYgen8M7u/mlvvEQUaO9tKKOy7K43M9U2aA3tPv0TuYYQFrEbK2eFQ==
+ dependencies:
+ "@vue/compiler-dom" "3.2.39"
+ "@vue/shared" "3.2.39"
+
+"@vue/compiler-ssr@3.3.4":
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz#9d1379abffa4f2b0cd844174ceec4a9721138777"
+ integrity sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==
+ dependencies:
+ "@vue/compiler-dom" "3.3.4"
+ "@vue/shared" "3.3.4"
+
+"@vue/component-compiler-utils@^3.1.0":
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz#f9f5fb53464b0c37b2c8d2f3fbfe44df60f61dc9"
+ integrity sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==
+ dependencies:
+ consolidate "^0.15.1"
+ hash-sum "^1.0.2"
+ lru-cache "^4.1.2"
+ merge-source-map "^1.1.0"
+ postcss "^7.0.36"
+ postcss-selector-parser "^6.0.2"
+ source-map "~0.6.1"
+ vue-template-es2015-compiler "^1.9.0"
+ optionalDependencies:
+ prettier "^1.18.2 || ^2.0.0"
+
+"@vue/reactivity-transform@3.2.39":
+ version "3.2.39"
+ resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.39.tgz#da6ae6c8fd77791b9ae21976720d116591e1c4aa"
+ integrity sha512-HGuWu864zStiWs9wBC6JYOP1E00UjMdDWIG5W+FpUx28hV3uz9ODOKVNm/vdOy/Pvzg8+OcANxAVC85WFBbl3A==
+ dependencies:
+ "@babel/parser" "^7.16.4"
+ "@vue/compiler-core" "3.2.39"
+ "@vue/shared" "3.2.39"
+ estree-walker "^2.0.2"
+ magic-string "^0.25.7"
+
+"@vue/reactivity-transform@3.3.4":
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz#52908476e34d6a65c6c21cd2722d41ed8ae51929"
+ integrity sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==
+ dependencies:
+ "@babel/parser" "^7.20.15"
+ "@vue/compiler-core" "3.3.4"
+ "@vue/shared" "3.3.4"
+ estree-walker "^2.0.2"
+ magic-string "^0.30.0"
+
+"@vue/reactivity@3.2.39":
+ version "3.2.39"
+ resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.39.tgz#e6e3615fe2288d4232b104640ddabd0729a78c80"
+ integrity sha512-vlaYX2a3qMhIZfrw3Mtfd+BuU+TZmvDrPMa+6lpfzS9k/LnGxkSuf0fhkP0rMGfiOHPtyKoU9OJJJFGm92beVQ==
+ dependencies:
+ "@vue/shared" "3.2.39"
+
+"@vue/reactivity@3.3.4":
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.3.4.tgz#a27a29c6cd17faba5a0e99fbb86ee951653e2253"
+ integrity sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==
+ dependencies:
+ "@vue/shared" "3.3.4"
+
+"@vue/runtime-core@3.2.39":
+ version "3.2.39"
+ resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.39.tgz#dc1faccab11b3e81197aba33fb30c9447c1d2c84"
+ integrity sha512-xKH5XP57JW5JW+8ZG1khBbuLakINTgPuINKL01hStWLTTGFOrM49UfCFXBcFvWmSbci3gmJyLl2EAzCaZWsx8g==
+ dependencies:
+ "@vue/reactivity" "3.2.39"
+ "@vue/shared" "3.2.39"
+
+"@vue/runtime-core@3.3.4":
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.3.4.tgz#4bb33872bbb583721b340f3088888394195967d1"
+ integrity sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==
+ dependencies:
+ "@vue/reactivity" "3.3.4"
+ "@vue/shared" "3.3.4"
+
+"@vue/runtime-dom@3.2.39":
+ version "3.2.39"
+ resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.39.tgz#4a8cb132bcef316e8151c5ed07fc7272eb064614"
+ integrity sha512-4G9AEJP+sLhsqf5wXcyKVWQKUhI+iWfy0hWQgea+CpaTD7BR0KdQzvoQdZhwCY6B3oleSyNLkLAQwm0ya/wNoA==
+ dependencies:
+ "@vue/runtime-core" "3.2.39"
+ "@vue/shared" "3.2.39"
+ csstype "^2.6.8"
+
+"@vue/runtime-dom@3.3.4":
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz#992f2579d0ed6ce961f47bbe9bfe4b6791251566"
+ integrity sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==
+ dependencies:
+ "@vue/runtime-core" "3.3.4"
+ "@vue/shared" "3.3.4"
+ csstype "^3.1.1"
+
+"@vue/server-renderer@3.2.39":
+ version "3.2.39"
+ resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.39.tgz#4358292d925233b0d8b54cf0513eaece8b2351c5"
+ integrity sha512-1yn9u2YBQWIgytFMjz4f/t0j43awKytTGVptfd3FtBk76t1pd8mxbek0G/DrnjJhd2V7mSTb5qgnxMYt8Z5iSQ==
+ dependencies:
+ "@vue/compiler-ssr" "3.2.39"
+ "@vue/shared" "3.2.39"
+
+"@vue/server-renderer@3.3.4":
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.3.4.tgz#ea46594b795d1536f29bc592dd0f6655f7ea4c4c"
+ integrity sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==
+ dependencies:
+ "@vue/compiler-ssr" "3.3.4"
+ "@vue/shared" "3.3.4"
+
+"@vue/shared@3.2.39":
+ version "3.2.39"
+ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.39.tgz#302df167559a1a5156da162d8cc6760cef67f8e3"
+ integrity sha512-D3dl2ZB9qE6mTuWPk9RlhDeP1dgNRUKC3NJxji74A4yL8M2MwlhLKUC/49WHjrNzSPug58fWx/yFbaTzGAQSBw==
+
+"@vue/shared@3.3.4":
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.3.4.tgz#06e83c5027f464eef861c329be81454bc8b70780"
+ integrity sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==
+
+"@vue/ui@^0.12.5":
+ version "0.12.5"
+ resolved "https://registry.yarnpkg.com/@vue/ui/-/ui-0.12.5.tgz#3c3456c8e4dcb3360a9228de0270921906bb7097"
+ integrity sha512-YBdl5y0XcM/RnLK8mxBQFS1SdcGtUnWcA0Aw4/geE8ZHehi3ZkBGocmZm0mK5HPlwH/+d0G+w18dbDjVaFWcKg==
+ dependencies:
+ focus-visible "^5.2.0"
+ v-tooltip "^3.0.0-alpha.20"
+ vue-resize "^1.0.0"
+
+"@vueuse/core@^10.7.2":
+ version "10.7.2"
+ resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-10.7.2.tgz#78917803a29a0bca1803a6521fdf7ff873f6e72c"
+ integrity sha512-AOyAL2rK0By62Hm+iqQn6Rbu8bfmbgaIMXcE3TSr7BdQ42wnSFlwIdPjInO62onYsEMK/yDMU8C6oGfDAtZ2qQ==
+ dependencies:
+ "@types/web-bluetooth" "^0.0.20"
+ "@vueuse/metadata" "10.7.2"
+ "@vueuse/shared" "10.7.2"
+ vue-demi ">=0.14.6"
+
+"@vueuse/metadata@10.7.2":
+ version "10.7.2"
+ resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-10.7.2.tgz#ba0187ce138c287fd80301afc5b0d6a97e563633"
+ integrity sha512-kCWPb4J2KGrwLtn1eJwaJD742u1k5h6v/St5wFe8Quih90+k2a0JP8BS4Zp34XUuJqS2AxFYMb1wjUL8HfhWsQ==
+
+"@vueuse/shared@10.7.2":
+ version "10.7.2"
+ resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-10.7.2.tgz#746441fbc08072371dd600a55883422c83fd0cab"
+ integrity sha512-qFbXoxS44pi2FkgFjPvF4h7c9oMDutpyBdcJdMYIMg9XyXli2meFMuaKn+UMgsClo//Th6+beeCgqweT/79BVA==
+ dependencies:
+ vue-demi ">=0.14.6"
+
+"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24"
+ integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==
+ dependencies:
+ "@webassemblyjs/helper-numbers" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+
+"@webassemblyjs/floating-point-hex-parser@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431"
+ integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==
+
+"@webassemblyjs/helper-api-error@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768"
+ integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==
+
+"@webassemblyjs/helper-buffer@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093"
+ integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==
+
+"@webassemblyjs/helper-numbers@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5"
+ integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==
+ dependencies:
+ "@webassemblyjs/floating-point-hex-parser" "1.11.6"
+ "@webassemblyjs/helper-api-error" "1.11.6"
+ "@xtuc/long" "4.2.2"
+
+"@webassemblyjs/helper-wasm-bytecode@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9"
+ integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==
+
+"@webassemblyjs/helper-wasm-section@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577"
+ integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.6"
+ "@webassemblyjs/helper-buffer" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/wasm-gen" "1.11.6"
+
+"@webassemblyjs/ieee754@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a"
+ integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==
+ dependencies:
+ "@xtuc/ieee754" "^1.2.0"
+
+"@webassemblyjs/leb128@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7"
+ integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==
+ dependencies:
+ "@xtuc/long" "4.2.2"
+
+"@webassemblyjs/utf8@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a"
+ integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==
+
+"@webassemblyjs/wasm-edit@^1.11.5":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab"
+ integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.6"
+ "@webassemblyjs/helper-buffer" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/helper-wasm-section" "1.11.6"
+ "@webassemblyjs/wasm-gen" "1.11.6"
+ "@webassemblyjs/wasm-opt" "1.11.6"
+ "@webassemblyjs/wasm-parser" "1.11.6"
+ "@webassemblyjs/wast-printer" "1.11.6"
+
+"@webassemblyjs/wasm-gen@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268"
+ integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/ieee754" "1.11.6"
+ "@webassemblyjs/leb128" "1.11.6"
+ "@webassemblyjs/utf8" "1.11.6"
+
+"@webassemblyjs/wasm-opt@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2"
+ integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.6"
+ "@webassemblyjs/helper-buffer" "1.11.6"
+ "@webassemblyjs/wasm-gen" "1.11.6"
+ "@webassemblyjs/wasm-parser" "1.11.6"
+
+"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1"
+ integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.6"
+ "@webassemblyjs/helper-api-error" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/ieee754" "1.11.6"
+ "@webassemblyjs/leb128" "1.11.6"
+ "@webassemblyjs/utf8" "1.11.6"
+
+"@webassemblyjs/wast-printer@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20"
+ integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.6"
+ "@xtuc/long" "4.2.2"
+
+"@webpack-cli/configtest@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5"
+ integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==
+
+"@webpack-cli/configtest@^2.1.1":
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646"
+ integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==
+
+"@webpack-cli/info@^1.5.0":
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1"
+ integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==
+ dependencies:
+ envinfo "^7.7.3"
+
+"@webpack-cli/info@^2.0.2":
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd"
+ integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==
+
+"@webpack-cli/serve@^1.7.0":
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1"
+ integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==
+
+"@webpack-cli/serve@^2.0.5":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e"
+ integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==
+
+"@xtuc/ieee754@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
+ integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==
+
+"@xtuc/long@4.2.2":
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
+ integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
+
+JSONStream@^1.0.4:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
+ integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==
+ dependencies:
+ jsonparse "^1.2.0"
+ through ">=2.2.7 <3"
+
+abbrev@1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
+ integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
+
+accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
+ integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
+ dependencies:
+ mime-types "~2.1.34"
+ negotiator "0.6.3"
+
+acorn-import-assertions@^1.9.0:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac"
+ integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==
+
+acorn-jsx@^5.3.2:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
+ integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
+
+acorn-node@^1.8.2:
+ version "1.8.2"
+ resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8"
+ integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==
+ dependencies:
+ acorn "^7.0.0"
+ acorn-walk "^7.0.0"
+ xtend "^4.0.2"
+
+acorn-walk@^7.0.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
+ integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
+
+acorn@^7.0.0:
+ version "7.4.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
+ integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
+
+acorn@^8.11.3, acorn@^8.8.2:
+ version "8.11.3"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a"
+ integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
+
+acorn@^8.5.0, acorn@^8.7.1:
+ version "8.8.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8"
+ integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==
+
+acorn@^8.9.0:
+ version "8.10.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
+ integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
+
+add-stream@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa"
+ integrity sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==
+
+agent-base@6, agent-base@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
+ integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
+ dependencies:
+ debug "4"
+
+agentkeepalive@^4.1.3:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717"
+ integrity sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==
+ dependencies:
+ debug "^4.1.0"
+ depd "^1.1.2"
+ humanize-ms "^1.2.1"
+
+aggregate-error@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
+ integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==
+ dependencies:
+ clean-stack "^2.0.0"
+ indent-string "^4.0.0"
+
+ajv-formats@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520"
+ integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==
+ dependencies:
+ ajv "^8.0.0"
+
+ajv-keywords@^3.5.2:
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
+ integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
+
+ajv-keywords@^5.0.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16"
+ integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==
+ dependencies:
+ fast-deep-equal "^3.1.3"
+
+ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5:
+ version "6.12.6"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+ 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"
+
+ajv@^8.0.0, ajv@^8.8.0:
+ version "8.11.0"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f"
+ integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ json-schema-traverse "^1.0.0"
+ require-from-string "^2.0.2"
+ uri-js "^4.2.2"
+
+algoliasearch@^4.0.0:
+ version "4.14.2"
+ resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.14.2.tgz#63f142583bfc3a9bd3cd4a1b098bf6fe58e56f6c"
+ integrity sha512-ngbEQonGEmf8dyEh5f+uOIihv4176dgbuOZspiuhmTTBRBuzWu3KCGHre6uHj5YyuC7pNvQGzB6ZNJyZi0z+Sg==
+ dependencies:
+ "@algolia/cache-browser-local-storage" "4.14.2"
+ "@algolia/cache-common" "4.14.2"
+ "@algolia/cache-in-memory" "4.14.2"
+ "@algolia/client-account" "4.14.2"
+ "@algolia/client-analytics" "4.14.2"
+ "@algolia/client-common" "4.14.2"
+ "@algolia/client-personalization" "4.14.2"
+ "@algolia/client-search" "4.14.2"
+ "@algolia/logger-common" "4.14.2"
+ "@algolia/logger-console" "4.14.2"
+ "@algolia/requester-browser-xhr" "4.14.2"
+ "@algolia/requester-common" "4.14.2"
+ "@algolia/requester-node-http" "4.14.2"
+ "@algolia/transporter" "4.14.2"
+
+ansi-escapes@^1.0.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
+ integrity sha512-wiXutNjDUlNEDWHcYH3jtZUhd3c4/VojassD8zHdHCY13xbZy2XbW+NKQwA0tWGBVzDA9qEzYwfoSsWmviidhw==
+
+ansi-escapes@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
+ integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
+
+ansi-escapes@^4.2.1:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
+ integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
+ dependencies:
+ type-fest "^0.21.3"
+
+ansi-html-community@^0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41"
+ integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==
+
+ansi-regex@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+ integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==
+
+ansi-regex@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1"
+ integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==
+
+ansi-regex@^4.1.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed"
+ integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==
+
+ansi-regex@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
+ integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+
+ansi-styles@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+ integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==
+
+ansi-styles@^3.2.0, ansi-styles@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+ dependencies:
+ color-convert "^1.9.0"
+
+ansi-styles@^4.0.0, ansi-styles@^4.1.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+ dependencies:
+ color-convert "^2.0.1"
+
+anymatch@~3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
+ integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
+aproba@^1.0.3:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
+ integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
+
+aproba@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc"
+ integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==
+
+arch@2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.1.tgz#8f5c2731aa35a30929221bb0640eed65175ec84e"
+ integrity sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg==
+
+archiver-utils@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2"
+ integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==
+ dependencies:
+ glob "^7.1.4"
+ graceful-fs "^4.2.0"
+ lazystream "^1.0.0"
+ lodash.defaults "^4.2.0"
+ lodash.difference "^4.5.0"
+ lodash.flatten "^4.4.0"
+ lodash.isplainobject "^4.0.6"
+ lodash.union "^4.6.0"
+ normalize-path "^3.0.0"
+ readable-stream "^2.0.0"
+
+archiver@^5.3.0:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.3.1.tgz#21e92811d6f09ecfce649fbefefe8c79e57cbbb6"
+ integrity sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==
+ dependencies:
+ archiver-utils "^2.1.0"
+ async "^3.2.3"
+ buffer-crc32 "^0.2.1"
+ readable-stream "^3.6.0"
+ readdir-glob "^1.0.0"
+ tar-stream "^2.2.0"
+ zip-stream "^4.1.0"
+
+are-docs-informative@^0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/are-docs-informative/-/are-docs-informative-0.0.2.tgz#387f0e93f5d45280373d387a59d34c96db321963"
+ integrity sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==
+
+are-we-there-yet@~1.1.2:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146"
+ integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==
+ dependencies:
+ delegates "^1.0.0"
+ readable-stream "^2.0.6"
+
+arg@^5.0.1:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
+ integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
+
+argparse@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
+ integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
+
+array-differ@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b"
+ integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==
+
+array-flatten@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+ integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==
+
+array-ify@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
+ integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==
+
+array-union@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
+ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
+array.prototype.reduce@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.4.tgz#8167e80089f78bff70a99e20bd4201d4663b0a6f"
+ integrity sha512-WnM+AjG/DvLRLo4DDl+r+SvCzYtD2Jd9oeBYMcEaI7t3fFrHY9M53/wdLcTvmZNQ70IU6Htj0emFkZ5TS+lrdw==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.2"
+ es-array-method-boxes-properly "^1.0.0"
+ is-string "^1.0.7"
+
+arrify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+ integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==
+
+arrify@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
+ integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
+
+asap@^2.0.0:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
+ integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==
+
+asn1@~0.2.3:
+ version "0.2.6"
+ resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d"
+ integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==
+ dependencies:
+ safer-buffer "~2.1.0"
+
+assert-plus@1.0.0, assert-plus@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+ integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==
+
+async@2.6.1:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610"
+ integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==
+ dependencies:
+ lodash "^4.17.10"
+
+async@^3.2.3:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
+ integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+ integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+
+at-least-node@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
+ integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
+
+atob@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
+ integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
+
+autoprefixer@^9, autoprefixer@^9.1.5:
+ version "9.8.8"
+ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.8.tgz#fd4bd4595385fa6f06599de749a4d5f7a474957a"
+ integrity sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==
+ dependencies:
+ browserslist "^4.12.0"
+ caniuse-lite "^1.0.30001109"
+ normalize-range "^0.1.2"
+ num2fraction "^1.2.2"
+ picocolors "^0.2.1"
+ postcss "^7.0.32"
+ postcss-value-parser "^4.1.0"
+
+aws-sign2@~0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
+ integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==
+
+aws4@^1.8.0:
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
+ integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
+
+axios@^0.21.1:
+ version "0.21.4"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
+ integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
+ dependencies:
+ follow-redirects "^1.14.0"
+
+babel-loader@^8.2.3:
+ version "8.2.5"
+ resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.5.tgz#d45f585e654d5a5d90f5350a779d7647c5ed512e"
+ integrity sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ==
+ dependencies:
+ find-cache-dir "^3.3.1"
+ loader-utils "^2.0.0"
+ make-dir "^3.1.0"
+ schema-utils "^2.6.5"
+
+babel-plugin-dynamic-import-node@^2.3.3:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3"
+ integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==
+ dependencies:
+ object.assign "^4.1.0"
+
+babel-plugin-polyfill-corejs2@^0.3.3:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122"
+ integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==
+ dependencies:
+ "@babel/compat-data" "^7.17.7"
+ "@babel/helper-define-polyfill-provider" "^0.3.3"
+ semver "^6.1.1"
+
+babel-plugin-polyfill-corejs3@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a"
+ integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==
+ dependencies:
+ "@babel/helper-define-polyfill-provider" "^0.3.3"
+ core-js-compat "^3.25.1"
+
+babel-plugin-polyfill-regenerator@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747"
+ integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==
+ dependencies:
+ "@babel/helper-define-polyfill-provider" "^0.3.3"
+
+balanced-match@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+base64-js@^1.3.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
+ integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
+
+base64id@2.0.0, base64id@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6"
+ integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==
+
+batch@0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
+ integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==
+
+bcrypt-pbkdf@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
+ integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==
+ dependencies:
+ tweetnacl "^0.14.3"
+
+before-after-hook@^2.2.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e"
+ integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==
+
+big.js@^5.2.2:
+ version "5.2.2"
+ resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
+ integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
+
+binary-extensions@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
+ integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
+
+bl@^4.0.3:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
+ integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
+ dependencies:
+ buffer "^5.5.0"
+ inherits "^2.0.4"
+ readable-stream "^3.4.0"
+
+bluebird@3.5.0:
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
+ integrity sha512-3LE8m8bqjGdoxfvf71yhFNrUcwy3NLy00SAo+b6MfJ8l+Bc2DzQ7mUHwX6pjK2AxfgV+YfsjCeVW3T5HLQTBsQ==
+
+bluebird@3.7.2, bluebird@^3.1.1:
+ version "3.7.2"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
+ integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
+
+body-parser@1.20.0:
+ version "1.20.0"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5"
+ integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==
+ dependencies:
+ bytes "3.1.2"
+ content-type "~1.0.4"
+ debug "2.6.9"
+ depd "2.0.0"
+ destroy "1.2.0"
+ http-errors "2.0.0"
+ iconv-lite "0.4.24"
+ on-finished "2.4.1"
+ qs "6.10.3"
+ raw-body "2.5.1"
+ type-is "~1.6.18"
+ unpipe "1.0.0"
+
+body-parser@1.20.1:
+ version "1.20.1"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668"
+ integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==
+ dependencies:
+ bytes "3.1.2"
+ content-type "~1.0.4"
+ debug "2.6.9"
+ depd "2.0.0"
+ destroy "1.2.0"
+ http-errors "2.0.0"
+ iconv-lite "0.4.24"
+ on-finished "2.4.1"
+ qs "6.11.0"
+ raw-body "2.5.1"
+ type-is "~1.6.18"
+ unpipe "1.0.0"
+
+bonjour-service@^1.0.11:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02"
+ integrity sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==
+ dependencies:
+ fast-deep-equal "^3.1.3"
+ multicast-dns "^7.2.5"
+
+boolbase@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+ integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
+
+boolean@^3.0.1:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b"
+ integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+brace-expansion@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
+ integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
+ dependencies:
+ balanced-match "^1.0.0"
+
+braces@^3.0.2, braces@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+ dependencies:
+ fill-range "^7.0.1"
+
+browserslist@^4.12.0, browserslist@^4.21.3, browserslist@^4.21.4:
+ version "4.21.4"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987"
+ integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==
+ dependencies:
+ caniuse-lite "^1.0.30001400"
+ electron-to-chromium "^1.4.251"
+ node-releases "^2.0.6"
+ update-browserslist-db "^1.0.9"
+
+browserslist@^4.21.10:
+ version "4.22.3"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.3.tgz#299d11b7e947a6b843981392721169e27d60c5a6"
+ integrity sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==
+ dependencies:
+ caniuse-lite "^1.0.30001580"
+ electron-to-chromium "^1.4.648"
+ node-releases "^2.0.14"
+ update-browserslist-db "^1.0.13"
+
+browserslist@^4.23.0:
+ version "4.23.0"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab"
+ integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==
+ dependencies:
+ caniuse-lite "^1.0.30001587"
+ electron-to-chromium "^1.4.668"
+ node-releases "^2.0.14"
+ update-browserslist-db "^1.0.13"
+
+buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3:
+ version "0.2.13"
+ resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
+ integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
+
+buffer-from@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
+ integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
+
+buffer@^5.5.0:
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
+ integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
+ dependencies:
+ base64-js "^1.3.1"
+ ieee754 "^1.1.13"
+
+builtin-modules@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6"
+ integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==
+
+builtins@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88"
+ integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==
+
+byline@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1"
+ integrity sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==
+
+byte-size@^7.0.0:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-7.0.1.tgz#b1daf3386de7ab9d706b941a748dbfc71130dee3"
+ integrity sha512-crQdqyCwhokxwV1UyDzLZanhkugAgft7vt0qbbdt60C6Zf3CAiGmtUCylbtYwrU6loOUw3euGrNtW1J651ot1A==
+
+bytes@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
+ integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==
+
+bytes@3.1.2, bytes@^3.0.0:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
+ integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
+
+cacache@^15.0.5, cacache@^15.2.0:
+ version "15.3.0"
+ resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb"
+ integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==
+ dependencies:
+ "@npmcli/fs" "^1.0.0"
+ "@npmcli/move-file" "^1.0.1"
+ chownr "^2.0.0"
+ fs-minipass "^2.0.0"
+ glob "^7.1.4"
+ infer-owner "^1.0.4"
+ lru-cache "^6.0.0"
+ minipass "^3.1.1"
+ minipass-collect "^1.0.2"
+ minipass-flush "^1.0.5"
+ minipass-pipeline "^1.2.2"
+ mkdirp "^1.0.3"
+ p-map "^4.0.0"
+ promise-inflight "^1.0.1"
+ rimraf "^3.0.2"
+ ssri "^8.0.1"
+ tar "^6.0.2"
+ unique-filename "^1.1.1"
+
+cacheable-request@^6.0.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912"
+ integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==
+ dependencies:
+ clone-response "^1.0.2"
+ get-stream "^5.1.0"
+ http-cache-semantics "^4.0.0"
+ keyv "^3.0.0"
+ lowercase-keys "^2.0.0"
+ normalize-url "^4.1.0"
+ responselike "^1.0.2"
+
+cachedir@1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-1.3.0.tgz#5e01928bf2d95b5edd94b0942188246740e0dbc4"
+ integrity sha512-O1ji32oyON9laVPJL1IZ5bmwd2cB46VfpxkDequezH+15FDzzVddEyrGEeX4WusDSqKxdyFdDQDEG1yo1GoWkg==
+ dependencies:
+ os-homedir "^1.0.1"
+
+call-bind@^1.0.0, call-bind@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
+ integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
+ dependencies:
+ function-bind "^1.1.1"
+ get-intrinsic "^1.0.2"
+
+call-me-maybe@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa"
+ integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==
+
+callsites@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
+ integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
+
+camelcase-css@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
+ integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
+
+camelcase-keys@^6.2.2:
+ version "6.2.2"
+ resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0"
+ integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==
+ dependencies:
+ camelcase "^5.3.1"
+ map-obj "^4.0.0"
+ quick-lru "^4.0.1"
+
+camelcase@^5.0.0, camelcase@^5.3.1:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+ integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
+caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001400:
+ version "1.0.30001410"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001410.tgz#b5a86366fbbf439d75dd3db1d21137a73e829f44"
+ integrity sha512-QoblBnuE+rG0lc3Ur9ltP5q47lbguipa/ncNMyyGuqPk44FxbScWAeEO+k5fSQ8WekdAK4mWqNs1rADDAiN5xQ==
+
+caniuse-lite@^1.0.30001580:
+ version "1.0.30001583"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001583.tgz#abb2970cc370801dc7e27bf290509dc132cfa390"
+ integrity sha512-acWTYaha8xfhA/Du/z4sNZjHUWjkiuoAi2LM+T/aL+kemKQgPT1xBb/YKjlQ0Qo8gvbHsGNplrEJ+9G3gL7i4Q==
+
+caniuse-lite@^1.0.30001587:
+ version "1.0.30001625"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001625.tgz#ead1b155ea691d6a87938754d3cb119c24465b03"
+ integrity sha512-4KE9N2gcRH+HQhpeiRZXd+1niLB/XNLAhSy4z7fI8EzcbcPoAqjNInxVHTiTwWfTIV4w096XG8OtCOCQQKPv3w==
+
+caseless@~0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+ integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==
+
+chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
+chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+ integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==
+ dependencies:
+ ansi-styles "^2.2.1"
+ escape-string-regexp "^1.0.2"
+ has-ansi "^2.0.0"
+ strip-ansi "^3.0.0"
+ supports-color "^2.0.0"
+
+chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+character-entities-legacy@^1.0.0:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1"
+ integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==
+
+character-entities@^1.0.0:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b"
+ integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==
+
+character-reference-invalid@^1.0.0:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560"
+ integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==
+
+chardet@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
+ integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
+
+check-more-types@2.24.0:
+ version "2.24.0"
+ resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600"
+ integrity sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==
+
+chokidar@^3.5.2, chokidar@^3.5.3:
+ version "3.5.3"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
+ integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
+ 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"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+chownr@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
+ integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
+
+chownr@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
+ integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
+
+chrome-trace-event@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
+ integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==
+
+ci-info@^1.5.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
+ integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
+
+ci-info@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
+ integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
+
+ci-info@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.0.0.tgz#65466f8b280fc019b9f50a5388115d17a63a44f2"
+ integrity sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==
+
+circular-json-es6@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/circular-json-es6/-/circular-json-es6-2.0.2.tgz#e4f4a093e49fb4b6aba1157365746112a78bd344"
+ integrity sha512-ODYONMMNb3p658Zv+Pp+/XPa5s6q7afhz3Tzyvo+VRh9WIrJ64J76ZC4GQxnlye/NesTn09jvOiuE8+xxfpwhQ==
+
+clean-regexp@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/clean-regexp/-/clean-regexp-1.0.0.tgz#8df7c7aae51fd36874e8f8d05b9180bc11a3fed7"
+ integrity sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==
+ dependencies:
+ escape-string-regexp "^1.0.5"
+
+clean-stack@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
+ integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
+
+cli-cursor@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
+ integrity sha512-25tABq090YNKkF6JH7lcwO0zFJTRke4Jcq9iX2nr/Sz0Cjjv4gckmwlW6Ty/aoyFd6z3ysR2hMGC2GFugmBo6A==
+ dependencies:
+ restore-cursor "^1.0.1"
+
+cli-cursor@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
+ integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==
+ dependencies:
+ restore-cursor "^2.0.0"
+
+cli-cursor@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
+ integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
+ dependencies:
+ restore-cursor "^3.1.0"
+
+cli-spinners@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c"
+ integrity sha512-t22oC6e068eEBQ86SO3arUtd1ojcA3/lz3Fp2g/oL/lmDlFz/2yD8JHiebeCGYmoAovYpwKq4T64Uq5j+28Q9w==
+
+cli-truncate@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574"
+ integrity sha512-f4r4yJnbT++qUPI9NR4XLDLq41gQ+uqnPItWG0F5ZkehuNiTTa3EY0S4AqTSUOeJ7/zU41oWPQSNkW5BqPL9bg==
+ dependencies:
+ slice-ansi "0.0.4"
+ string-width "^1.0.1"
+
+cli-width@^2.0.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
+ integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
+
+cli-width@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
+ integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
+
+cliui@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
+ integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==
+ dependencies:
+ string-width "^3.1.0"
+ strip-ansi "^5.2.0"
+ wrap-ansi "^5.1.0"
+
+cliui@^7.0.2:
+ version "7.0.4"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
+ integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
+ dependencies:
+ string-width "^4.2.0"
+ strip-ansi "^6.0.0"
+ wrap-ansi "^7.0.0"
+
+cliui@^8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
+ integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
+ dependencies:
+ string-width "^4.2.0"
+ strip-ansi "^6.0.1"
+ wrap-ansi "^7.0.0"
+
+clone-deep@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
+ integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
+ dependencies:
+ is-plain-object "^2.0.4"
+ kind-of "^6.0.2"
+ shallow-clone "^3.0.0"
+
+clone-response@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3"
+ integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==
+ dependencies:
+ mimic-response "^1.0.0"
+
+clone@^1.0.2:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
+ integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==
+
+cmd-shim@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-4.1.0.tgz#b3a904a6743e9fede4148c6f3800bf2a08135bdd"
+ integrity sha512-lb9L7EM4I/ZRVuljLPEtUJOP+xiQVknZ4ZMpMgEp4JzNldPb27HU03hi6K1/6CoIuit/Zm/LQXySErFeXxDprw==
+ dependencies:
+ mkdirp-infer-owner "^2.0.0"
+
+code-point-at@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+ integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==
+
+color-convert@^1.9.0:
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+ dependencies:
+ color-name "1.1.3"
+
+color-convert@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+ dependencies:
+ color-name "~1.1.4"
+
+color-name@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+ integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
+
+color-name@^1.0.0, color-name@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+color-string@^1.9.0:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4"
+ integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==
+ dependencies:
+ color-name "^1.0.0"
+ simple-swizzle "^0.2.2"
+
+color@^4.0.1:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a"
+ integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==
+ dependencies:
+ color-convert "^2.0.1"
+ color-string "^1.9.0"
+
+colorette@^2.0.10, colorette@^2.0.14:
+ version "2.0.19"
+ resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798"
+ integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==
+
+columnify@^1.5.4:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.6.0.tgz#6989531713c9008bb29735e61e37acf5bd553cf3"
+ integrity sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==
+ dependencies:
+ strip-ansi "^6.0.1"
+ wcwidth "^1.0.0"
+
+combined-stream@^1.0.6, combined-stream@~1.0.6:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
+commander@2, commander@^2.20.0:
+ version "2.20.3"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+commander@2.15.1:
+ version "2.15.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
+ integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
+
+commander@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
+ integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
+
+commander@^7.0.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
+ integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
+
+commander@^8.0.0:
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
+ integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
+
+comment-parser@1.4.1, comment-parser@^1.4.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.4.1.tgz#bdafead37961ac079be11eb7ec65c4d021eaf9cc"
+ integrity sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==
+
+common-tags@1.8.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937"
+ integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==
+
+commondir@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+ integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==
+
+compare-func@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3"
+ integrity sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==
+ dependencies:
+ array-ify "^1.0.0"
+ dot-prop "^5.1.0"
+
+compress-commons@^4.1.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-4.1.1.tgz#df2a09a7ed17447642bad10a85cc9a19e5c42a7d"
+ integrity sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==
+ dependencies:
+ buffer-crc32 "^0.2.13"
+ crc32-stream "^4.0.2"
+ normalize-path "^3.0.0"
+ readable-stream "^3.6.0"
+
+compressible@~2.0.16:
+ version "2.0.18"
+ resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
+ integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
+ dependencies:
+ mime-db ">= 1.43.0 < 2"
+
+compression@^1.7.4:
+ version "1.7.4"
+ resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
+ integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==
+ dependencies:
+ accepts "~1.3.5"
+ bytes "3.0.0"
+ compressible "~2.0.16"
+ debug "2.6.9"
+ on-headers "~1.0.2"
+ safe-buffer "5.1.2"
+ vary "~1.1.2"
+
+compute-scroll-into-view@^1.0.17:
+ version "1.0.17"
+ resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz#6a88f18acd9d42e9cf4baa6bec7e0522607ab7ab"
+ integrity sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+
+concat-stream@1.6.2:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
+ integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
+ dependencies:
+ buffer-from "^1.0.0"
+ inherits "^2.0.3"
+ readable-stream "^2.2.2"
+ typedarray "^0.0.6"
+
+concat-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1"
+ integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==
+ dependencies:
+ buffer-from "^1.0.0"
+ inherits "^2.0.3"
+ readable-stream "^3.0.2"
+ typedarray "^0.0.6"
+
+concurrently@^5.1.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-5.3.0.tgz#7500de6410d043c912b2da27de3202cb489b1e7b"
+ integrity sha512-8MhqOB6PWlBfA2vJ8a0bSFKATOdWlHiQlk11IfmQBPaHVP8oP2gsh2MObE6UR3hqDHqvaIvLTyceNW6obVuFHQ==
+ dependencies:
+ chalk "^2.4.2"
+ date-fns "^2.0.1"
+ lodash "^4.17.15"
+ read-pkg "^4.0.1"
+ rxjs "^6.5.2"
+ spawn-command "^0.0.2-1"
+ supports-color "^6.1.0"
+ tree-kill "^1.2.2"
+ yargs "^13.3.0"
+
+config-chain@^1.1.11, config-chain@^1.1.12:
+ version "1.1.13"
+ resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4"
+ integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==
+ dependencies:
+ ini "^1.3.4"
+ proto-list "~1.2.1"
+
+connect-history-api-fallback@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8"
+ integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==
+
+console-control-strings@^1.0.0, console-control-strings@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
+ integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==
+
+consolidate@^0.15.1:
+ version "0.15.1"
+ resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7"
+ integrity sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==
+ dependencies:
+ bluebird "^3.1.1"
+
+content-disposition@0.5.4:
+ version "0.5.4"
+ resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
+ integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
+ dependencies:
+ safe-buffer "5.2.1"
+
+content-type@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+ integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
+
+conventional-changelog-angular@^5.0.12:
+ version "5.0.13"
+ resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz#896885d63b914a70d4934b59d2fe7bde1832b28c"
+ integrity sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==
+ dependencies:
+ compare-func "^2.0.0"
+ q "^1.5.1"
+
+conventional-changelog-core@^4.2.2:
+ version "4.2.4"
+ resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz#e50d047e8ebacf63fac3dc67bf918177001e1e9f"
+ integrity sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==
+ dependencies:
+ add-stream "^1.0.0"
+ conventional-changelog-writer "^5.0.0"
+ conventional-commits-parser "^3.2.0"
+ dateformat "^3.0.0"
+ get-pkg-repo "^4.0.0"
+ git-raw-commits "^2.0.8"
+ git-remote-origin-url "^2.0.0"
+ git-semver-tags "^4.1.1"
+ lodash "^4.17.15"
+ normalize-package-data "^3.0.0"
+ q "^1.5.1"
+ read-pkg "^3.0.0"
+ read-pkg-up "^3.0.0"
+ through2 "^4.0.0"
+
+conventional-changelog-preset-loader@^2.3.4:
+ version "2.3.4"
+ resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz#14a855abbffd59027fd602581f1f34d9862ea44c"
+ integrity sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==
+
+conventional-changelog-writer@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz#e0757072f045fe03d91da6343c843029e702f359"
+ integrity sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==
+ dependencies:
+ conventional-commits-filter "^2.0.7"
+ dateformat "^3.0.0"
+ handlebars "^4.7.7"
+ json-stringify-safe "^5.0.1"
+ lodash "^4.17.15"
+ meow "^8.0.0"
+ semver "^6.0.0"
+ split "^1.0.0"
+ through2 "^4.0.0"
+
+conventional-commits-filter@^2.0.7:
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz#f8d9b4f182fce00c9af7139da49365b136c8a0b3"
+ integrity sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==
+ dependencies:
+ lodash.ismatch "^4.4.0"
+ modify-values "^1.0.0"
+
+conventional-commits-parser@^3.2.0:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz#a7d3b77758a202a9b2293d2112a8d8052c740972"
+ integrity sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==
+ dependencies:
+ JSONStream "^1.0.4"
+ is-text-path "^1.0.1"
+ lodash "^4.17.15"
+ meow "^8.0.0"
+ split2 "^3.0.0"
+ through2 "^4.0.0"
+
+conventional-recommended-bump@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz#cfa623285d1de554012f2ffde70d9c8a22231f55"
+ integrity sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==
+ dependencies:
+ concat-stream "^2.0.0"
+ conventional-changelog-preset-loader "^2.3.4"
+ conventional-commits-filter "^2.0.7"
+ conventional-commits-parser "^3.2.0"
+ git-raw-commits "^2.0.8"
+ git-semver-tags "^4.1.1"
+ meow "^8.0.0"
+ q "^1.5.1"
+
+convert-source-map@^1.7.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
+ integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==
+ dependencies:
+ safe-buffer "~5.1.1"
+
+cookie-signature@1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+ integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
+
+cookie@0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
+ integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
+
+cookie@~0.4.1:
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432"
+ integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
+
+core-js-compat@^3.25.1:
+ version "3.25.2"
+ resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.25.2.tgz#7875573586809909c69e03ef310810c1969ee138"
+ integrity sha512-TxfyECD4smdn3/CjWxczVtJqVLEEC2up7/82t7vC0AzNogr+4nQ8vyF7abxAuTXWvjTClSbvGhU0RgqA4ToQaQ==
+ dependencies:
+ browserslist "^4.21.4"
+
+core-js-compat@^3.37.0:
+ version "3.37.1"
+ resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.37.1.tgz#c844310c7852f4bdf49b8d339730b97e17ff09ee"
+ integrity sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==
+ dependencies:
+ browserslist "^4.23.0"
+
+core-js@^3.20.2, core-js@^3.6.4:
+ version "3.25.2"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.2.tgz#2d3670c1455432b53fa780300a6fc1bd8304932c"
+ integrity sha512-YB4IAT1bjEfxTJ1XYy11hJAKskO+qmhuDBM8/guIfMz4JvdsAQAqvyb97zXX7JgSrfPLG5mRGFWJwJD39ruq2A==
+
+core-util-is@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+ integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==
+
+core-util-is@~1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
+ integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
+
+cors@~2.8.5:
+ version "2.8.5"
+ resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
+ integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
+ dependencies:
+ object-assign "^4"
+ vary "^1"
+
+cosmiconfig@^7.0.0, cosmiconfig@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d"
+ integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==
+ 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"
+
+crc-32@^1.2.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff"
+ integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==
+
+crc32-stream@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-4.0.2.tgz#c922ad22b38395abe9d3870f02fa8134ed709007"
+ integrity sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==
+ dependencies:
+ crc-32 "^1.2.0"
+ readable-stream "^3.4.0"
+
+cross-env@^5.2.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.2.1.tgz#b2c76c1ca7add66dc874d11798466094f551b34d"
+ integrity sha512-1yHhtcfAd1r4nwQgknowuUNfIT9E8dOMMspC36g45dN+iD1blloi7xp8X/xAIDnjHWyt1uQ8PHk2fkNaym7soQ==
+ dependencies:
+ cross-spawn "^6.0.5"
+
+cross-spawn@^6.0.0, cross-spawn@^6.0.5:
+ version "6.0.5"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
+ integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
+ dependencies:
+ nice-try "^1.0.4"
+ path-key "^2.0.1"
+ semver "^5.5.0"
+ shebang-command "^1.2.0"
+ which "^1.2.9"
+
+cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
+ integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+css-color-names@^0.0.4:
+ version "0.0.4"
+ resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
+ integrity sha512-zj5D7X1U2h2zsXOAM8EyUREBnnts6H+Jm+d1M2DbiQQcUtnqgQsMrdo8JW9R80YFUmIdBZeMu5wvYM7hcgWP/Q==
+
+css-loader@^5.2.4:
+ version "5.2.7"
+ resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.2.7.tgz#9b9f111edf6fb2be5dc62525644cbc9c232064ae"
+ integrity sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==
+ dependencies:
+ icss-utils "^5.1.0"
+ loader-utils "^2.0.0"
+ postcss "^8.2.15"
+ postcss-modules-extract-imports "^3.0.0"
+ postcss-modules-local-by-default "^4.0.0"
+ postcss-modules-scope "^3.0.0"
+ postcss-modules-values "^4.0.0"
+ postcss-value-parser "^4.1.0"
+ schema-utils "^3.0.0"
+ semver "^7.3.5"
+
+css-parse@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-2.0.0.tgz#a468ee667c16d81ccf05c58c38d2a97c780dbfd4"
+ integrity sha512-UNIFik2RgSbiTwIW1IsFwXWn6vs+bYdq83LKTSOsx7NJR7WII9dxewkHLltfTLVppoUApHV0118a4RZRI9FLwA==
+ dependencies:
+ css "^2.0.0"
+
+css-unit-converter@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21"
+ integrity sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==
+
+css@^2.0.0:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929"
+ integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==
+ dependencies:
+ inherits "^2.0.3"
+ source-map "^0.6.1"
+ source-map-resolve "^0.5.2"
+ urix "^0.1.0"
+
+cssesc@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
+ integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
+
+csstype@^2.6.8:
+ version "2.6.21"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e"
+ integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==
+
+csstype@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
+ integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==
+
+csstype@^3.1.1:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"
+ integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==
+
+cypress@=3.4.1, cypress@^3.1.0:
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.4.1.tgz#ca2e4e9864679da686c6a6189603efd409664c30"
+ integrity sha512-1HBS7t9XXzkt6QHbwfirWYty8vzxNMawGj1yI+Fu6C3/VZJ8UtUngMW6layqwYZzLTZV8tiDpdCNBypn78V4Dg==
+ dependencies:
+ "@cypress/listr-verbose-renderer" "0.4.1"
+ "@cypress/xvfb" "1.2.4"
+ arch "2.1.1"
+ bluebird "3.5.0"
+ cachedir "1.3.0"
+ chalk "2.4.2"
+ check-more-types "2.24.0"
+ commander "2.15.1"
+ common-tags "1.8.0"
+ debug "3.2.6"
+ execa "0.10.0"
+ executable "4.1.1"
+ extract-zip "1.6.7"
+ fs-extra "5.0.0"
+ getos "3.1.1"
+ is-ci "1.2.1"
+ is-installed-globally "0.1.0"
+ lazy-ass "1.6.0"
+ listr "0.12.0"
+ lodash "4.17.15"
+ log-symbols "2.2.0"
+ minimist "1.2.0"
+ moment "2.24.0"
+ ramda "0.24.1"
+ request "2.88.0"
+ request-progress "3.0.0"
+ supports-color "5.5.0"
+ tmp "0.1.0"
+ url "0.11.0"
+ yauzl "2.10.0"
+
+d3-array@1, d3-array@^1.1.1, d3-array@^1.2.0:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f"
+ integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==
+
+d3-axis@1:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-1.0.12.tgz#cdf20ba210cfbb43795af33756886fb3638daac9"
+ integrity sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==
+
+d3-brush@1:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-1.1.6.tgz#b0a22c7372cabec128bdddf9bddc058592f89e9b"
+ integrity sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==
+ dependencies:
+ d3-dispatch "1"
+ d3-drag "1"
+ d3-interpolate "1"
+ d3-selection "1"
+ d3-transition "1"
+
+d3-chord@1:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-1.0.6.tgz#309157e3f2db2c752f0280fedd35f2067ccbb15f"
+ integrity sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==
+ dependencies:
+ d3-array "1"
+ d3-path "1"
+
+d3-collection@1:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.7.tgz#349bd2aa9977db071091c13144d5e4f16b5b310e"
+ integrity sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==
+
+d3-color@1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.4.1.tgz#c52002bf8846ada4424d55d97982fef26eb3bc8a"
+ integrity sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==
+
+d3-contour@1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-1.3.2.tgz#652aacd500d2264cb3423cee10db69f6f59bead3"
+ integrity sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==
+ dependencies:
+ d3-array "^1.1.1"
+
+d3-dispatch@1:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.6.tgz#00d37bcee4dd8cd97729dd893a0ac29caaba5d58"
+ integrity sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==
+
+d3-drag@1:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-1.2.5.tgz#2537f451acd39d31406677b7dc77c82f7d988f70"
+ integrity sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==
+ dependencies:
+ d3-dispatch "1"
+ d3-selection "1"
+
+d3-dsv@1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-1.2.0.tgz#9d5f75c3a5f8abd611f74d3f5847b0d4338b885c"
+ integrity sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==
+ dependencies:
+ commander "2"
+ iconv-lite "0.4"
+ rw "1"
+
+d3-ease@1:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.7.tgz#9a834890ef8b8ae8c558b2fe55bd57f5993b85e2"
+ integrity sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==
+
+d3-fetch@1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-1.2.0.tgz#15ce2ecfc41b092b1db50abd2c552c2316cf7fc7"
+ integrity sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==
+ dependencies:
+ d3-dsv "1"
+
+d3-force@1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-1.2.1.tgz#fd29a5d1ff181c9e7f0669e4bd72bdb0e914ec0b"
+ integrity sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==
+ dependencies:
+ d3-collection "1"
+ d3-dispatch "1"
+ d3-quadtree "1"
+ d3-timer "1"
+
+d3-format@1:
+ version "1.4.5"
+ resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.5.tgz#374f2ba1320e3717eb74a9356c67daee17a7edb4"
+ integrity sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==
+
+d3-geo@1:
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.12.1.tgz#7fc2ab7414b72e59fbcbd603e80d9adc029b035f"
+ integrity sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==
+ dependencies:
+ d3-array "1"
+
+d3-hierarchy@1:
+ version "1.1.9"
+ resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz#2f6bee24caaea43f8dc37545fa01628559647a83"
+ integrity sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==
+
+d3-interpolate@1:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.4.0.tgz#526e79e2d80daa383f9e0c1c1c7dcc0f0583e987"
+ integrity sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==
+ dependencies:
+ d3-color "1"
+
+d3-path@1:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf"
+ integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==
+
+d3-polygon@1:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-1.0.6.tgz#0bf8cb8180a6dc107f518ddf7975e12abbfbd38e"
+ integrity sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==
+
+d3-quadtree@1:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-1.0.7.tgz#ca8b84df7bb53763fe3c2f24bd435137f4e53135"
+ integrity sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==
+
+d3-random@1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-1.1.2.tgz#2833be7c124360bf9e2d3fd4f33847cfe6cab291"
+ integrity sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==
+
+d3-scale-chromatic@1:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz#54e333fc78212f439b14641fb55801dd81135a98"
+ integrity sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==
+ dependencies:
+ d3-color "1"
+ d3-interpolate "1"
+
+d3-scale@2:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-2.2.2.tgz#4e880e0b2745acaaddd3ede26a9e908a9e17b81f"
+ integrity sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==
+ dependencies:
+ d3-array "^1.2.0"
+ d3-collection "1"
+ d3-format "1"
+ d3-interpolate "1"
+ d3-time "1"
+ d3-time-format "2"
+
+d3-selection@1, d3-selection@^1.1.0:
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.4.2.tgz#dcaa49522c0dbf32d6c1858afc26b6094555bc5c"
+ integrity sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==
+
+d3-shape@1:
+ version "1.3.7"
+ resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7"
+ integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==
+ dependencies:
+ d3-path "1"
+
+d3-time-format@2:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.3.0.tgz#107bdc028667788a8924ba040faf1fbccd5a7850"
+ integrity sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==
+ dependencies:
+ d3-time "1"
+
+d3-time@1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1"
+ integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==
+
+d3-timer@1:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.10.tgz#dfe76b8a91748831b13b6d9c793ffbd508dd9de5"
+ integrity sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==
+
+d3-transition@1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-1.3.2.tgz#a98ef2151be8d8600543434c1ca80140ae23b398"
+ integrity sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==
+ dependencies:
+ d3-color "1"
+ d3-dispatch "1"
+ d3-ease "1"
+ d3-interpolate "1"
+ d3-selection "^1.1.0"
+ d3-timer "1"
+
+d3-voronoi@1:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.4.tgz#dd3c78d7653d2bb359284ae478645d95944c8297"
+ integrity sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==
+
+d3-zoom@1:
+ version "1.8.3"
+ resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-1.8.3.tgz#b6a3dbe738c7763121cd05b8a7795ffe17f4fc0a"
+ integrity sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==
+ dependencies:
+ d3-dispatch "1"
+ d3-drag "1"
+ d3-interpolate "1"
+ d3-selection "1"
+ d3-transition "1"
+
+d3@^5.16.0:
+ version "5.16.0"
+ resolved "https://registry.yarnpkg.com/d3/-/d3-5.16.0.tgz#9c5e8d3b56403c79d4ed42fbd62f6113f199c877"
+ integrity sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==
+ dependencies:
+ d3-array "1"
+ d3-axis "1"
+ d3-brush "1"
+ d3-chord "1"
+ d3-collection "1"
+ d3-color "1"
+ d3-contour "1"
+ d3-dispatch "1"
+ d3-drag "1"
+ d3-dsv "1"
+ d3-ease "1"
+ d3-fetch "1"
+ d3-force "1"
+ d3-format "1"
+ d3-geo "1"
+ d3-hierarchy "1"
+ d3-interpolate "1"
+ d3-path "1"
+ d3-polygon "1"
+ d3-quadtree "1"
+ d3-random "1"
+ d3-scale "2"
+ d3-scale-chromatic "1"
+ d3-selection "1"
+ d3-shape "1"
+ d3-time "1"
+ d3-time-format "2"
+ d3-timer "1"
+ d3-transition "1"
+ d3-voronoi "1"
+ d3-zoom "1"
+
+dargs@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc"
+ integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==
+
+dashdash@^1.12.0:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
+ integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==
+ dependencies:
+ assert-plus "^1.0.0"
+
+date-fns@^1.27.2:
+ version "1.30.1"
+ resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c"
+ integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==
+
+date-fns@^2.0.1:
+ version "2.29.3"
+ resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8"
+ integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==
+
+dateformat@^3.0.0:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
+ integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
+
+debug@2.6.9:
+ version "2.6.9"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+ integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+ dependencies:
+ ms "2.0.0"
+
+debug@3.2.6:
+ version "3.2.6"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
+ integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
+ dependencies:
+ ms "^2.1.1"
+
+debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2:
+ version "4.3.4"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+ dependencies:
+ ms "2.1.2"
+
+debug@4.3.2:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
+ integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
+ dependencies:
+ ms "2.1.2"
+
+debug@^3.1.0, debug@^3.2.7:
+ version "3.2.7"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
+ integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
+ dependencies:
+ ms "^2.1.1"
+
+debug@~3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+ integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
+ dependencies:
+ ms "2.0.0"
+
+debuglog@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
+ integrity sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==
+
+decamelize-keys@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
+ integrity sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==
+ dependencies:
+ decamelize "^1.1.0"
+ map-obj "^1.0.0"
+
+decamelize@^1.1.0, decamelize@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+ integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
+
+decode-uri-component@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
+ integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==
+
+decompress-response@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
+ integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==
+ dependencies:
+ mimic-response "^1.0.0"
+
+dedent@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
+ integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==
+
+deep-is@^0.1.3:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
+ integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
+
+default-gateway@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71"
+ integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==
+ dependencies:
+ execa "^5.0.0"
+
+defaults@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
+ integrity sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==
+ dependencies:
+ clone "^1.0.2"
+
+defer-to-connect@^1.0.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
+ integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
+
+define-lazy-prop@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
+ integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
+
+define-properties@^1.1.3, define-properties@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1"
+ integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==
+ dependencies:
+ has-property-descriptors "^1.0.0"
+ object-keys "^1.1.1"
+
+defined@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
+ integrity sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+ integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+
+delegates@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
+ integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==
+
+depd@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
+ integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
+
+depd@^1.1.2, depd@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+ integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==
+
+deprecation@^2.0.0, deprecation@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919"
+ integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==
+
+destroy@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
+ integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
+
+detect-indent@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
+ integrity sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==
+
+detect-indent@^6.0.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6"
+ integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==
+
+detect-node@^2.0.4:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1"
+ integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==
+
+detective@^5.2.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.1.tgz#6af01eeda11015acb0e73f933242b70f24f91034"
+ integrity sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==
+ dependencies:
+ acorn-node "^1.8.2"
+ defined "^1.0.0"
+ minimist "^1.2.6"
+
+dezalgo@^1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81"
+ integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==
+ dependencies:
+ asap "^2.0.0"
+ wrappy "1"
+
+didyoumean@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
+ integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
+
+dir-glob@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
+ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+ dependencies:
+ path-type "^4.0.0"
+
+dlv@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
+ integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
+
+dns-packet@^5.2.2:
+ version "5.6.1"
+ resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f"
+ integrity sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==
+ dependencies:
+ "@leichtgewicht/ip-codec" "^2.0.1"
+
+doctrine@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
+ integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
+ dependencies:
+ esutils "^2.0.2"
+
+dot-prop@^5.1.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
+ integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==
+ dependencies:
+ is-obj "^2.0.0"
+
+dot-prop@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083"
+ integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==
+ dependencies:
+ is-obj "^2.0.0"
+
+duplexer3@^0.1.4:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e"
+ integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==
+
+duplexer@^0.1.1, duplexer@~0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
+ integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
+
+earcut@^2.2.4:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/earcut/-/earcut-2.2.4.tgz#6d02fd4d68160c114825d06890a92ecaae60343a"
+ integrity sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==
+
+ecc-jsbn@~0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
+ integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==
+ dependencies:
+ jsbn "~0.1.0"
+ safer-buffer "^2.1.0"
+
+ee-first@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+ integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
+
+electron-to-chromium@^1.4.251:
+ version "1.4.260"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.260.tgz#9aa3348d037686b47ccc5d3b48fe417b1f20017a"
+ integrity sha512-1GxPM2Bdz1AjuNjho9/TqJfxM7KZ7R8s4vA5cbbIoVacQXfvZlV+d7Y1lu4BhGzEBfjjhakr3NXKqN0PxPXIsg==
+
+electron-to-chromium@^1.4.648:
+ version "1.4.656"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.656.tgz#b374fb7cab9b782a5bc967c0ce0e19826186b9c9"
+ integrity sha512-9AQB5eFTHyR3Gvt2t/NwR0le2jBSUNwCnMbUCejFWHD+so4tH40/dRLgoE+jxlPeWS43XJewyvCv+I8LPMl49Q==
+
+electron-to-chromium@^1.4.668:
+ version "1.4.787"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.787.tgz#3eedd0a3b8be2b9e96e21675d399786ad90b99ed"
+ integrity sha512-d0EFmtLPjctczO3LogReyM2pbBiiZbnsKnGF+cdZhsYzHm/A0GV7W94kqzLD8SN4O3f3iHlgLUChqghgyznvCQ==
+
+electron@^21.0.1:
+ version "21.0.1"
+ resolved "https://registry.yarnpkg.com/electron/-/electron-21.0.1.tgz#753669454a86a89fd70ba9614c79f789fb177c34"
+ integrity sha512-jLVSLakd0fO2GPnW4xXQrI93R464jeFb2ISngqRP3wpwH96XqeANkuAYLAr9TVhfQMCIWnuPROBZ+NU7nuk0WA==
+ dependencies:
+ "@electron/get" "^1.14.1"
+ "@types/node" "^16.11.26"
+ extract-zip "^2.0.1"
+
+elegant-spinner@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e"
+ integrity sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==
+
+emoji-regex@^7.0.1:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
+ integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
+
+emoji-regex@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
+ integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+
+emojis-list@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
+ integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
+
+encodeurl@^1.0.2, encodeurl@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+ integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
+
+encoding@^0.1.12:
+ version "0.1.13"
+ resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
+ integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==
+ dependencies:
+ iconv-lite "^0.6.2"
+
+end-of-stream@^1.1.0, end-of-stream@^1.4.1:
+ version "1.4.4"
+ resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
+ integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
+ dependencies:
+ once "^1.4.0"
+
+engine.io-client@~6.2.1:
+ version "6.2.2"
+ resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.2.2.tgz#c6c5243167f5943dcd9c4abee1bfc634aa2cbdd0"
+ integrity sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==
+ dependencies:
+ "@socket.io/component-emitter" "~3.1.0"
+ debug "~4.3.1"
+ engine.io-parser "~5.0.3"
+ ws "~8.2.3"
+ xmlhttprequest-ssl "~2.0.0"
+
+engine.io-parser@~5.0.3:
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.4.tgz#0b13f704fa9271b3ec4f33112410d8f3f41d0fc0"
+ integrity sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==
+
+engine.io@~6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.2.0.tgz#003bec48f6815926f2b1b17873e576acd54f41d0"
+ integrity sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==
+ dependencies:
+ "@types/cookie" "^0.4.1"
+ "@types/cors" "^2.8.12"
+ "@types/node" ">=10.0.0"
+ accepts "~1.3.4"
+ base64id "2.0.0"
+ cookie "~0.4.1"
+ cors "~2.8.5"
+ debug "~4.3.1"
+ engine.io-parser "~5.0.3"
+ ws "~8.2.3"
+
+enhanced-resolve@^5.15.0:
+ version "5.15.0"
+ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35"
+ integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==
+ dependencies:
+ graceful-fs "^4.2.4"
+ tapable "^2.2.0"
+
+env-paths@^2.2.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
+ integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
+
+envinfo@^7.7.3, envinfo@^7.7.4:
+ version "7.8.1"
+ resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"
+ integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==
+
+err-code@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9"
+ integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==
+
+error-ex@^1.3.1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
+ integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
+ dependencies:
+ is-arrayish "^0.2.1"
+
+error-stack-parser@^2.0.0:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286"
+ integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==
+ dependencies:
+ stackframe "^1.3.4"
+
+es-abstract@^1.19.0, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.1:
+ version "1.20.3"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.3.tgz#90b143ff7aedc8b3d189bcfac7f1e3e3f81e9da1"
+ integrity sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw==
+ 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.6"
+ 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"
+
+es-array-method-boxes-properly@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e"
+ integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==
+
+es-module-lexer@^1.2.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz#41ea21b43908fe6a287ffcbe4300f790555331f5"
+ integrity sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==
+
+es-to-primitive@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
+ integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
+ dependencies:
+ is-callable "^1.1.4"
+ is-date-object "^1.0.1"
+ is-symbol "^1.0.2"
+
+es6-error@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d"
+ integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==
+
+esbuild-android-64@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz#505f41832884313bbaffb27704b8bcaa2d8616be"
+ integrity sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==
+
+esbuild-android-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.15.9.tgz#4a7eb320ca8d3a305f14792061fd9614ccebb7c0"
+ integrity sha512-HQCX7FJn9T4kxZQkhPjNZC7tBWZqJvhlLHPU2SFzrQB/7nDXjmTIFpFTjt7Bd1uFpeXmuwf5h5fZm+x/hLnhbw==
+
+esbuild-android-arm64@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz#8ce69d7caba49646e009968fe5754a21a9871771"
+ integrity sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==
+
+esbuild-android-arm64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.15.9.tgz#c948e5686df20857ad361ec67e070d40d7cab985"
+ integrity sha512-E6zbLfqbFVCNEKircSHnPiSTsm3fCRxeIMPfrkS33tFjIAoXtwegQfVZqMGR0FlsvVxp2NEDOUz+WW48COCjSg==
+
+esbuild-darwin-64@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz#24ba67b9a8cb890a3c08d9018f887cc221cdda25"
+ integrity sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==
+
+esbuild-darwin-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.15.9.tgz#25f564fa4b39c1cec84dc46bce5634fdbce1d5e4"
+ integrity sha512-gI7dClcDN/HHVacZhTmGjl0/TWZcGuKJ0I7/xDGJwRQQn7aafZGtvagOFNmuOq+OBFPhlPv1T6JElOXb0unkSQ==
+
+esbuild-darwin-arm64@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz#3f7cdb78888ee05e488d250a2bdaab1fa671bf73"
+ integrity sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==
+
+esbuild-darwin-arm64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.9.tgz#60faea3ed95d15239536aa88d06bb82b29278a86"
+ integrity sha512-VZIMlcRN29yg/sv7DsDwN+OeufCcoTNaTl3Vnav7dL/nvsApD7uvhVRbgyMzv0zU/PP0xRhhIpTyc7lxEzHGSw==
+
+esbuild-freebsd-64@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz#09250f997a56ed4650f3e1979c905ffc40bbe94d"
+ integrity sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==
+
+esbuild-freebsd-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.9.tgz#0339ef1c90a919175e7816788224517896657a0e"
+ integrity sha512-uM4z5bTvuAXqPxrI204txhlsPIolQPWRMLenvGuCPZTnnGlCMF2QLs0Plcm26gcskhxewYo9LkkmYSS5Czrb5A==
+
+esbuild-freebsd-arm64@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz#bafb46ed04fc5f97cbdb016d86947a79579f8e48"
+ integrity sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==
+
+esbuild-freebsd-arm64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.9.tgz#32abfc0be3ae3dd38e5a86a9beadbbcf592f1b57"
+ integrity sha512-HHDjT3O5gWzicGdgJ5yokZVN9K9KG05SnERwl9nBYZaCjcCgj/sX8Ps1jvoFSfNCO04JSsHSOWo4qvxFuj8FoA==
+
+esbuild-linux-32@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz#e2a8c4a8efdc355405325033fcebeb941f781fe5"
+ integrity sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==
+
+esbuild-linux-32@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.15.9.tgz#93581348a4da7ed2b29bc5539f2605ad7fcee77b"
+ integrity sha512-AQIdE8FugGt1DkcekKi5ycI46QZpGJ/wqcMr7w6YUmOmp2ohQ8eO4sKUsOxNOvYL7hGEVwkndSyszR6HpVHLFg==
+
+esbuild-linux-64@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz#de5fdba1c95666cf72369f52b40b03be71226652"
+ integrity sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==
+
+esbuild-linux-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.15.9.tgz#0d171e7946c95d0d3ed4826026af2c5632d7dcc4"
+ integrity sha512-4RXjae7g6Qs7StZyiYyXTZXBlfODhb1aBVAjd+ANuPmMhWthQilWo7rFHwJwL7DQu1Fjej2sODAVwLbcIVsAYQ==
+
+esbuild-linux-arm64@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz#dae4cd42ae9787468b6a5c158da4c84e83b0ce8b"
+ integrity sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==
+
+esbuild-linux-arm64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.9.tgz#9838795a3720cbe736d3bc20621bd366eac22f24"
+ integrity sha512-a+bTtxJmYmk9d+s2W4/R1SYKDDAldOKmWjWP0BnrWtDbvUBNOm++du0ysPju4mZVoEFgS1yLNW+VXnG/4FNwdQ==
+
+esbuild-linux-arm@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz#a2c1dff6d0f21dbe8fc6998a122675533ddfcd59"
+ integrity sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==
+
+esbuild-linux-arm@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.15.9.tgz#dce96cd817bc7376f6af3967649c4ab1f2f79506"
+ integrity sha512-3Zf2GVGUOI7XwChH3qrnTOSqfV1V4CAc/7zLVm4lO6JT6wbJrTgEYCCiNSzziSju+J9Jhf9YGWk/26quWPC6yQ==
+
+esbuild-linux-mips64le@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz#d9918e9e4cb972f8d6dae8e8655bf9ee131eda34"
+ integrity sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==
+
+esbuild-linux-mips64le@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.9.tgz#0335a0739e61aa97cb9b4a018e3facfcca9cdcfd"
+ integrity sha512-Zn9HSylDp89y+TRREMDoGrc3Z4Hs5u56ozZLQCiZAUx2+HdbbXbWdjmw3FdTJ/i7t5Cew6/Q+6kfO3KCcFGlyw==
+
+esbuild-linux-ppc64le@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz#3f9a0f6d41073fb1a640680845c7de52995f137e"
+ integrity sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==
+
+esbuild-linux-ppc64le@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.9.tgz#18482afb95b8a705e2da0a59d7131bff221281f9"
+ integrity sha512-OEiOxNAMH9ENFYqRsWUj3CWyN3V8P3ZXyfNAtX5rlCEC/ERXrCEFCJji/1F6POzsXAzxvUJrTSTCy7G6BhA6Fw==
+
+esbuild-linux-riscv64@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz#618853c028178a61837bc799d2013d4695e451c8"
+ integrity sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==
+
+esbuild-linux-riscv64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.9.tgz#03b6f9708272c117006b9ce1c9ae8aab91b5a5b6"
+ integrity sha512-ukm4KsC3QRausEFjzTsOZ/qqazw0YvJsKmfoZZm9QW27OHjk2XKSQGGvx8gIEswft/Sadp03/VZvAaqv5AIwNA==
+
+esbuild-linux-s390x@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz#d1885c4c5a76bbb5a0fe182e2c8c60eb9e29f2a6"
+ integrity sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==
+
+esbuild-linux-s390x@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.9.tgz#65fb645623d575780f155f0ee52935e62f9cca4f"
+ integrity sha512-uDOQEH55wQ6ahcIKzQr3VyjGc6Po/xblLGLoUk3fVL1qjlZAibtQr6XRfy5wPJLu/M2o0vQKLq4lyJ2r1tWKcw==
+
+esbuild-loader@^2.13.0:
+ version "2.20.0"
+ resolved "https://registry.yarnpkg.com/esbuild-loader/-/esbuild-loader-2.20.0.tgz#28fcff0142fa7bd227512d69f31e9a6e202bb88f"
+ integrity sha512-dr+j8O4w5RvqZ7I4PPB4EIyVTd679EBQnMm+JBB7av+vu05Zpje2IpK5N3ld1VWa+WxrInIbNFAg093+E1aRsA==
+ dependencies:
+ esbuild "^0.15.6"
+ joycon "^3.0.1"
+ json5 "^2.2.0"
+ loader-utils "^2.0.0"
+ tapable "^2.2.0"
+ webpack-sources "^2.2.0"
+
+esbuild-netbsd-64@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz#69ae917a2ff241b7df1dbf22baf04bd330349e81"
+ integrity sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==
+
+esbuild-netbsd-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.9.tgz#7894297bb9e11f3d2f6f31efecd1be4e181f0d54"
+ integrity sha512-yWgxaYTQz+TqX80wXRq6xAtb7GSBAp6gqLKfOdANg9qEmAI1Bxn04IrQr0Mzm4AhxvGKoHzjHjMgXbCCSSDxcw==
+
+esbuild-openbsd-64@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz#db4c8495287a350a6790de22edea247a57c5d47b"
+ integrity sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==
+
+esbuild-openbsd-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.9.tgz#0f9d4c6b6772ae50d491d68ad4cc028300dda7c0"
+ integrity sha512-JmS18acQl4iSAjrEha1MfEmUMN4FcnnrtTaJ7Qg0tDCOcgpPPQRLGsZqhes0vmx8VA6IqRyScqXvaL7+Q0Uf3A==
+
+esbuild-sunos-64@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz#54287ee3da73d3844b721c21bc80c1dc7e1bf7da"
+ integrity sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==
+
+esbuild-sunos-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.15.9.tgz#c32b7ce574b08f814de810ce7c1e34b843768126"
+ integrity sha512-UKynGSWpzkPmXW3D2UMOD9BZPIuRaSqphxSCwScfEE05Be3KAmvjsBhht1fLzKpiFVJb0BYMd4jEbWMyJ/z1hQ==
+
+esbuild-windows-32@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz#f8aaf9a5667630b40f0fb3aa37bf01bbd340ce31"
+ integrity sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==
+
+esbuild-windows-32@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.15.9.tgz#37a8f7cfccdb2177cd46613a1a1e1fcb419d36df"
+ integrity sha512-aqXvu4/W9XyTVqO/hw3rNxKE1TcZiEYHPsXM9LwYmKSX9/hjvfIJzXwQBlPcJ/QOxedfoMVH0YnhhQ9Ffb0RGA==
+
+esbuild-windows-64@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz#bf54b51bd3e9b0f1886ffdb224a4176031ea0af4"
+ integrity sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==
+
+esbuild-windows-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.15.9.tgz#5fe1e76fc13dd7f520febecaea110b6f1649c7b2"
+ integrity sha512-zm7h91WUmlS4idMtjvCrEeNhlH7+TNOmqw5dJPJZrgFaxoFyqYG6CKDpdFCQXdyKpD5yvzaQBOMVTCBVKGZDEg==
+
+esbuild-windows-arm64@0.14.54:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz#937d15675a15e4b0e4fafdbaa3a01a776a2be982"
+ integrity sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==
+
+esbuild-windows-arm64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.9.tgz#98504428f7ba7d2cfc11940be68ee1139173fdce"
+ integrity sha512-yQEVIv27oauAtvtuhJVfSNMztJJX47ismRS6Sv2QMVV9RM+6xjbMWuuwM2nxr5A2/gj/mu2z9YlQxiwoFRCfZA==
+
+esbuild@^0.11.20:
+ version "0.11.23"
+ resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.11.23.tgz#c42534f632e165120671d64db67883634333b4b8"
+ integrity sha512-iaiZZ9vUF5wJV8ob1tl+5aJTrwDczlvGP0JoMmnpC2B0ppiMCu8n8gmy5ZTGl5bcG081XBVn+U+jP+mPFm5T5Q==
+
+esbuild@^0.14.27:
+ version "0.14.54"
+ resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.54.tgz#8b44dcf2b0f1a66fc22459943dccf477535e9aa2"
+ integrity sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==
+ optionalDependencies:
+ "@esbuild/linux-loong64" "0.14.54"
+ esbuild-android-64 "0.14.54"
+ esbuild-android-arm64 "0.14.54"
+ esbuild-darwin-64 "0.14.54"
+ esbuild-darwin-arm64 "0.14.54"
+ esbuild-freebsd-64 "0.14.54"
+ esbuild-freebsd-arm64 "0.14.54"
+ esbuild-linux-32 "0.14.54"
+ esbuild-linux-64 "0.14.54"
+ esbuild-linux-arm "0.14.54"
+ esbuild-linux-arm64 "0.14.54"
+ esbuild-linux-mips64le "0.14.54"
+ esbuild-linux-ppc64le "0.14.54"
+ esbuild-linux-riscv64 "0.14.54"
+ esbuild-linux-s390x "0.14.54"
+ esbuild-netbsd-64 "0.14.54"
+ esbuild-openbsd-64 "0.14.54"
+ esbuild-sunos-64 "0.14.54"
+ esbuild-windows-32 "0.14.54"
+ esbuild-windows-64 "0.14.54"
+ esbuild-windows-arm64 "0.14.54"
+
+esbuild@^0.15.6:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.15.9.tgz#33fb18b67b85004b6f7616bec955ca4b3e58935d"
+ integrity sha512-OnYr1rkMVxtmMHIAKZLMcEUlJmqcbxBz9QoBU8G9v455na0fuzlT/GLu6l+SRghrk0Mm2fSSciMmzV43Q8e0Gg==
+ optionalDependencies:
+ "@esbuild/android-arm" "0.15.9"
+ "@esbuild/linux-loong64" "0.15.9"
+ esbuild-android-64 "0.15.9"
+ esbuild-android-arm64 "0.15.9"
+ esbuild-darwin-64 "0.15.9"
+ esbuild-darwin-arm64 "0.15.9"
+ esbuild-freebsd-64 "0.15.9"
+ esbuild-freebsd-arm64 "0.15.9"
+ esbuild-linux-32 "0.15.9"
+ esbuild-linux-64 "0.15.9"
+ esbuild-linux-arm "0.15.9"
+ esbuild-linux-arm64 "0.15.9"
+ esbuild-linux-mips64le "0.15.9"
+ esbuild-linux-ppc64le "0.15.9"
+ esbuild-linux-riscv64 "0.15.9"
+ esbuild-linux-s390x "0.15.9"
+ esbuild-netbsd-64 "0.15.9"
+ esbuild-openbsd-64 "0.15.9"
+ esbuild-sunos-64 "0.15.9"
+ esbuild-windows-32 "0.15.9"
+ esbuild-windows-64 "0.15.9"
+ esbuild-windows-arm64 "0.15.9"
+
+escalade@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
+ integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
+
+escape-html@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+ integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
+
+escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+ integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
+
+escape-string-regexp@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
+ integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
+
+eslint-compat-utils@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/eslint-compat-utils/-/eslint-compat-utils-0.1.2.tgz#f45e3b5ced4c746c127cf724fb074cd4e730d653"
+ integrity sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==
+
+eslint-compat-utils@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/eslint-compat-utils/-/eslint-compat-utils-0.5.0.tgz#f7b2eb2befec25a370fac76934d3f9189f312a65"
+ integrity sha512-dc6Y8tzEcSYZMHa+CMPLi/hyo1FzNeonbhJL7Ol0ccuKQkwopJcJBA9YL/xmMTLU1eKigXo9vj9nALElWYSowg==
+ dependencies:
+ semver "^7.5.4"
+
+eslint-config-flat-gitignore@^0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/eslint-config-flat-gitignore/-/eslint-config-flat-gitignore-0.1.5.tgz#43997c3ca00fb679d10bdb73afa78467d83e2fa4"
+ integrity sha512-hEZLwuZjDBGDERA49c2q7vxc8sCGv8EdBp6PQYzGOMcHIgrfG9YOM6s/4jx24zhD+wnK9AI8mgN5RxSss5nClQ==
+ dependencies:
+ find-up "^7.0.0"
+ parse-gitignore "^2.0.0"
+
+eslint-flat-config-utils@^0.2.5:
+ version "0.2.5"
+ resolved "https://registry.yarnpkg.com/eslint-flat-config-utils/-/eslint-flat-config-utils-0.2.5.tgz#7d229ffb347897051f49ccc000d198deec15ea16"
+ integrity sha512-iO+yLZtC/LKgACerkpvsZ6NoRVB2sxT04mOpnNcEM1aTwKy+6TsT46PUvrML4y2uVBS6I67hRCd2JiKAPaL/Uw==
+ dependencies:
+ "@types/eslint" "^8.56.10"
+ pathe "^1.1.2"
+
+eslint-import-resolver-node@^0.3.9:
+ version "0.3.9"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac"
+ integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==
+ dependencies:
+ debug "^3.2.7"
+ is-core-module "^2.13.0"
+ resolve "^1.22.4"
+
+eslint-merge-processors@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-merge-processors/-/eslint-merge-processors-0.1.0.tgz#30ac4c59725a63d12a9677de7d2b2ec2a09fb779"
+ integrity sha512-IvRXXtEajLeyssvW4wJcZ2etxkR9mUf4zpNwgI+m/Uac9RfXHskuJefkHUcawVzePnd6xp24enp5jfgdHzjRdQ==
+
+eslint-plugin-antfu@^2.3.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-antfu/-/eslint-plugin-antfu-2.3.3.tgz#e88efd0c6547efeafaf5ffe5e86da3a182e73434"
+ integrity sha512-TAgYNuc20QyKw8NXtpzR3LeMTTv1qAJVKkjCVzjRSGiSR1EetEY7LRgQVhcgP/C1FnI87isQERAIkKvkYyLq0Q==
+ dependencies:
+ "@antfu/utils" "^0.7.8"
+
+eslint-plugin-command@^0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-command/-/eslint-plugin-command-0.2.3.tgz#53a28215e66b66fc6e3f4790fb7e7aa0abdd5c09"
+ integrity sha512-1bBYNfjZg60N2ZpLV5ATYSYyueIJ+zl5yKrTs0UFDdnyu07dNSZ7Xplnc+Wb6SXTdc1sIaoIrnuyhvztcltX6A==
+ dependencies:
+ "@es-joy/jsdoccomment" "^0.43.0"
+
+eslint-plugin-es-x@^7.5.0:
+ version "7.5.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-es-x/-/eslint-plugin-es-x-7.5.0.tgz#d08d9cd155383e35156c48f736eb06561d07ba92"
+ integrity sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==
+ dependencies:
+ "@eslint-community/eslint-utils" "^4.1.2"
+ "@eslint-community/regexpp" "^4.6.0"
+ eslint-compat-utils "^0.1.2"
+
+eslint-plugin-eslint-comments@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz#9e1cd7b4413526abb313933071d7aba05ca12ffa"
+ integrity sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==
+ dependencies:
+ escape-string-regexp "^1.0.5"
+ ignore "^5.0.5"
+
+eslint-plugin-import-x@^0.5.1:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-import-x/-/eslint-plugin-import-x-0.5.1.tgz#0781096ee737ccfc0f9a028d286839bfa53b1080"
+ integrity sha512-2JK8bbFOLes+gG6tgdnM8safCxMAj4u2wjX8X1BRFPfnY7Ct2hFYESoIcVwABX/DDcdpQFLGtKmzbNEWJZD9iQ==
+ dependencies:
+ "@typescript-eslint/utils" "^7.4.0"
+ debug "^4.3.4"
+ doctrine "^3.0.0"
+ eslint-import-resolver-node "^0.3.9"
+ get-tsconfig "^4.7.3"
+ is-glob "^4.0.3"
+ minimatch "^9.0.3"
+ semver "^7.6.0"
+ tslib "^2.6.2"
+
+eslint-plugin-jsdoc@^48.2.6:
+ version "48.2.7"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.7.tgz#2610b6fa1a9ba45c8296c2f335e0360bbd238772"
+ integrity sha512-fYj3roTnkFL9OFFTB129rico8lerC5G8Vp2ZW9SjO9RNWG0exVvI+i/Y8Bpm1ufjR0uvT38xtoab/U0Hp8Ybog==
+ dependencies:
+ "@es-joy/jsdoccomment" "~0.43.1"
+ are-docs-informative "^0.0.2"
+ comment-parser "1.4.1"
+ debug "^4.3.4"
+ escape-string-regexp "^4.0.0"
+ esquery "^1.5.0"
+ semver "^7.6.2"
+ spdx-expression-parse "^4.0.0"
+
+eslint-plugin-jsonc@^2.16.0:
+ version "2.16.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.16.0.tgz#e90eca15aa2e172f5aca52a77fc8c819f52862d7"
+ integrity sha512-Af/ZL5mgfb8FFNleH6KlO4/VdmDuTqmM+SPnWcdoWywTetv7kq+vQe99UyQb9XO3b0OWLVuTH7H0d/PXYCMdSg==
+ dependencies:
+ "@eslint-community/eslint-utils" "^4.2.0"
+ eslint-compat-utils "^0.5.0"
+ espree "^9.6.1"
+ graphemer "^1.4.0"
+ jsonc-eslint-parser "^2.0.4"
+ natural-compare "^1.4.0"
+ synckit "^0.6.0"
+
+eslint-plugin-markdown@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-markdown/-/eslint-plugin-markdown-5.0.0.tgz#a2b69bce83e85838111d44c84b2d6721452dbb73"
+ integrity sha512-kY2u9yDhzvfZ0kmRTsvgm3mTnvZgTSGIIPeHg3yesSx4R5CTCnITUjCPhzCD1MUhNcqHU5Tr6lzx+02EclVPbw==
+ dependencies:
+ mdast-util-from-markdown "^0.8.5"
+
+eslint-plugin-n@^17.7.0:
+ version "17.7.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-n/-/eslint-plugin-n-17.7.0.tgz#90b4f777cefb9bf0d91dafa94347961c4e8a072c"
+ integrity sha512-4Jg4ZKVE4VjHig2caBqPHYNW5na84RVufUuipFLJbgM/G57O6FdpUKJbHakCDJb/yjQuyqVzYWRtU3HNYaZUwg==
+ dependencies:
+ "@eslint-community/eslint-utils" "^4.4.0"
+ enhanced-resolve "^5.15.0"
+ eslint-plugin-es-x "^7.5.0"
+ get-tsconfig "^4.7.0"
+ globals "^15.0.0"
+ ignore "^5.2.4"
+ minimatch "^9.0.0"
+ semver "^7.5.3"
+
+eslint-plugin-no-only-tests@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.1.0.tgz#f38e4935c6c6c4842bf158b64aaa20c366fe171b"
+ integrity sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw==
+
+eslint-plugin-perfectionist@^2.10.0:
+ version "2.10.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-2.10.0.tgz#15cf9f5545ce2db24d1ccdf3226645a097480faf"
+ integrity sha512-P+tdrkHeMWBc55+DZsoDOAftV1WCsEoHaKm6JC7zajFus/syfT4vUPBFb3atGFSuyaVnGQGHlcKpP9X3Q0gH/w==
+ dependencies:
+ "@typescript-eslint/utils" "^6.13.0 || ^7.0.0"
+ minimatch "^9.0.3"
+ natural-compare-lite "^1.4.0"
+
+eslint-plugin-regexp@^2.6.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-regexp/-/eslint-plugin-regexp-2.6.0.tgz#54b9ca535662ca2c59ca211b7723ef22e2b6681b"
+ integrity sha512-FCL851+kislsTEQEMioAlpDuK5+E5vs0hi1bF8cFlPlHcEjeRhuAzEsGikXRreE+0j4WhW2uO54MqTjXtYOi3A==
+ dependencies:
+ "@eslint-community/eslint-utils" "^4.2.0"
+ "@eslint-community/regexpp" "^4.9.1"
+ comment-parser "^1.4.0"
+ jsdoc-type-pratt-parser "^4.0.0"
+ refa "^0.12.1"
+ regexp-ast-analysis "^0.7.1"
+ scslre "^0.3.0"
+
+eslint-plugin-toml@^0.11.0:
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-toml/-/eslint-plugin-toml-0.11.0.tgz#d81d783cbe5052a7d107ab62f36c76da849eb4c5"
+ integrity sha512-sau+YvPU4fWTjB+qtBt3n8WS87aoDCs+BVbSUAemGaIsRNbvR9uEk+Tt892iLHTGvp/DPWYoCX4/8DoyAbB+sQ==
+ dependencies:
+ debug "^4.1.1"
+ eslint-compat-utils "^0.5.0"
+ lodash "^4.17.19"
+ toml-eslint-parser "^0.9.0"
+
+eslint-plugin-unicorn@^53.0.0:
+ version "53.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-53.0.0.tgz#df3a5c9ecabeb759e6fd867b2d84198466ac8c4d"
+ integrity sha512-kuTcNo9IwwUCfyHGwQFOK/HjJAYzbODHN3wP0PgqbW+jbXqpNWxNVpVhj2tO9SixBwuAdmal8rVcWKBxwFnGuw==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.24.5"
+ "@eslint-community/eslint-utils" "^4.4.0"
+ "@eslint/eslintrc" "^3.0.2"
+ ci-info "^4.0.0"
+ clean-regexp "^1.0.0"
+ core-js-compat "^3.37.0"
+ esquery "^1.5.0"
+ indent-string "^4.0.0"
+ is-builtin-module "^3.2.1"
+ jsesc "^3.0.2"
+ pluralize "^8.0.0"
+ read-pkg-up "^7.0.1"
+ regexp-tree "^0.1.27"
+ regjsparser "^0.10.0"
+ semver "^7.6.1"
+ strip-indent "^3.0.0"
+
+eslint-plugin-unused-imports@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.2.0.tgz#63a98c9ad5f622cd9f830f70bc77739f25ccfe0d"
+ integrity sha512-6uXyn6xdINEpxE1MtDjxQsyXB37lfyO2yKGVVgtD7WEWQGORSOZjgrD6hBhvGv4/SO+TOlS+UnC6JppRqbuwGQ==
+ dependencies:
+ eslint-rule-composer "^0.3.0"
+
+eslint-plugin-vitest@^0.5.4:
+ version "0.5.4"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-vitest/-/eslint-plugin-vitest-0.5.4.tgz#2838a40ee116ba7c15eb6132df31371d960e3bf5"
+ integrity sha512-um+odCkccAHU53WdKAw39MY61+1x990uXjSPguUCq3VcEHdqJrOb8OTMrbYlY6f9jAKx7x98kLVlIe3RJeJqoQ==
+ dependencies:
+ "@typescript-eslint/utils" "^7.7.1"
+
+eslint-plugin-vue@^9.26.0:
+ version "9.26.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.26.0.tgz#bf7f5cce62c8f878059b91edae44d22974133af5"
+ integrity sha512-eTvlxXgd4ijE1cdur850G6KalZqk65k1JKoOI2d1kT3hr8sPD07j1q98FRFdNnpxBELGPWxZmInxeHGF/GxtqQ==
+ dependencies:
+ "@eslint-community/eslint-utils" "^4.4.0"
+ globals "^13.24.0"
+ natural-compare "^1.4.0"
+ nth-check "^2.1.1"
+ postcss-selector-parser "^6.0.15"
+ semver "^7.6.0"
+ vue-eslint-parser "^9.4.2"
+ xml-name-validator "^4.0.0"
+
+eslint-plugin-yml@^1.14.0:
+ version "1.14.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-yml/-/eslint-plugin-yml-1.14.0.tgz#98a019dfe4eb6837f881fb80d564df79cb05d8d9"
+ integrity sha512-ESUpgYPOcAYQO9czugcX5OqRvn/ydDVwGCPXY4YjPqc09rHaUVUA6IE6HLQys4rXk/S+qx3EwTd1wHCwam/OWQ==
+ dependencies:
+ debug "^4.3.2"
+ eslint-compat-utils "^0.5.0"
+ lodash "^4.17.21"
+ natural-compare "^1.4.0"
+ yaml-eslint-parser "^1.2.1"
+
+eslint-processor-vue-blocks@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/eslint-processor-vue-blocks/-/eslint-processor-vue-blocks-0.1.2.tgz#d472e0a5efe15e9eab5c3f2e2518c9a121097805"
+ integrity sha512-PfpJ4uKHnqeL/fXUnzYkOax3aIenlwewXRX8jFinA1a2yCFnLgMuiH3xvCgvHHUlV2xJWQHbCTdiJWGwb3NqpQ==
+
+eslint-rule-composer@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9"
+ integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==
+
+eslint-scope@5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^4.1.1"
+
+eslint-scope@^7.1.1:
+ version "7.2.2"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f"
+ integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^5.2.0"
+
+eslint-scope@^8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.0.1.tgz#a9601e4b81a0b9171657c343fb13111688963cfc"
+ integrity sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^5.2.0"
+
+eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3:
+ version "3.4.3"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
+ integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
+
+eslint-visitor-keys@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb"
+ integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==
+
+eslint@^9.3.0:
+ version "9.3.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.3.0.tgz#36a96db84592618d6ed9074d677e92f4e58c08b9"
+ integrity sha512-5Iv4CsZW030lpUqHBapdPo3MJetAPtejVW8B84GIcIIv8+ohFaddXsrn1Gn8uD9ijDb+kcYKFUVmC8qG8B2ORQ==
+ dependencies:
+ "@eslint-community/eslint-utils" "^4.2.0"
+ "@eslint-community/regexpp" "^4.6.1"
+ "@eslint/eslintrc" "^3.1.0"
+ "@eslint/js" "9.3.0"
+ "@humanwhocodes/config-array" "^0.13.0"
+ "@humanwhocodes/module-importer" "^1.0.1"
+ "@humanwhocodes/retry" "^0.3.0"
+ "@nodelib/fs.walk" "^1.2.8"
+ ajv "^6.12.4"
+ chalk "^4.0.0"
+ cross-spawn "^7.0.2"
+ debug "^4.3.2"
+ escape-string-regexp "^4.0.0"
+ eslint-scope "^8.0.1"
+ eslint-visitor-keys "^4.0.0"
+ espree "^10.0.1"
+ esquery "^1.4.2"
+ esutils "^2.0.2"
+ fast-deep-equal "^3.1.3"
+ file-entry-cache "^8.0.0"
+ find-up "^5.0.0"
+ glob-parent "^6.0.2"
+ ignore "^5.2.0"
+ imurmurhash "^0.1.4"
+ is-glob "^4.0.0"
+ is-path-inside "^3.0.3"
+ 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.3"
+ strip-ansi "^6.0.1"
+ text-table "^0.2.0"
+
+espree@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-10.0.1.tgz#600e60404157412751ba4a6f3a2ee1a42433139f"
+ integrity sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==
+ dependencies:
+ acorn "^8.11.3"
+ acorn-jsx "^5.3.2"
+ eslint-visitor-keys "^4.0.0"
+
+espree@^9.0.0, espree@^9.3.1, espree@^9.6.1:
+ version "9.6.1"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f"
+ integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==
+ dependencies:
+ acorn "^8.9.0"
+ acorn-jsx "^5.3.2"
+ eslint-visitor-keys "^3.4.1"
+
+esquery@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5"
+ integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==
+ dependencies:
+ estraverse "^5.1.0"
+
+esquery@^1.4.2, esquery@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b"
+ integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==
+ dependencies:
+ estraverse "^5.1.0"
+
+esrecurse@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
+ integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+ dependencies:
+ estraverse "^5.2.0"
+
+estraverse@^4.1.1:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
+ integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+
+estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
+ integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
+
+estree-walker@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
+ integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
+
+esutils@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
+ integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+
+etag@~1.8.1:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+ integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
+
+event-stream@=3.3.4:
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
+ integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==
+ dependencies:
+ duplexer "~0.1.1"
+ from "~0"
+ map-stream "~0.1.0"
+ pause-stream "0.0.11"
+ split "0.3"
+ stream-combiner "~0.0.4"
+ through "~2.3.1"
+
+eventemitter3@^3.1.0:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
+ integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==
+
+eventemitter3@^4.0.0, eventemitter3@^4.0.4:
+ version "4.0.7"
+ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
+ integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
+
+events@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
+ integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+
+execa@0.10.0:
+ version "0.10.0"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50"
+ integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==
+ dependencies:
+ cross-spawn "^6.0.0"
+ get-stream "^3.0.0"
+ is-stream "^1.1.0"
+ npm-run-path "^2.0.0"
+ p-finally "^1.0.0"
+ signal-exit "^3.0.0"
+ strip-eof "^1.0.0"
+
+execa@5.1.1, execa@^5.0.0:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
+ integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
+ dependencies:
+ cross-spawn "^7.0.3"
+ get-stream "^6.0.0"
+ human-signals "^2.1.0"
+ is-stream "^2.0.0"
+ merge-stream "^2.0.0"
+ npm-run-path "^4.0.1"
+ onetime "^5.1.2"
+ signal-exit "^3.0.3"
+ strip-final-newline "^2.0.0"
+
+execa@^4.0.3:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a"
+ integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==
+ dependencies:
+ cross-spawn "^7.0.0"
+ get-stream "^5.0.0"
+ human-signals "^1.1.1"
+ is-stream "^2.0.0"
+ merge-stream "^2.0.0"
+ npm-run-path "^4.0.0"
+ onetime "^5.1.0"
+ signal-exit "^3.0.2"
+ strip-final-newline "^2.0.0"
+
+executable@4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c"
+ integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==
+ dependencies:
+ pify "^2.2.0"
+
+exit-hook@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
+ integrity sha512-MsG3prOVw1WtLXAZbM3KiYtooKR1LvxHh3VHsVtIy0uiUu8usxgB/94DP2HxtD/661lLdB6yzQ09lGJSQr6nkg==
+
+express@^4.17.1:
+ version "4.18.1"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf"
+ integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==
+ dependencies:
+ accepts "~1.3.8"
+ array-flatten "1.1.1"
+ body-parser "1.20.0"
+ content-disposition "0.5.4"
+ content-type "~1.0.4"
+ cookie "0.5.0"
+ cookie-signature "1.0.6"
+ debug "2.6.9"
+ depd "2.0.0"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ finalhandler "1.2.0"
+ fresh "0.5.2"
+ http-errors "2.0.0"
+ merge-descriptors "1.0.1"
+ methods "~1.1.2"
+ on-finished "2.4.1"
+ parseurl "~1.3.3"
+ path-to-regexp "0.1.7"
+ proxy-addr "~2.0.7"
+ qs "6.10.3"
+ range-parser "~1.2.1"
+ safe-buffer "5.2.1"
+ send "0.18.0"
+ serve-static "1.15.0"
+ setprototypeof "1.2.0"
+ statuses "2.0.1"
+ type-is "~1.6.18"
+ utils-merge "1.0.1"
+ vary "~1.1.2"
+
+express@^4.17.3:
+ version "4.18.2"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
+ integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
+ dependencies:
+ accepts "~1.3.8"
+ array-flatten "1.1.1"
+ body-parser "1.20.1"
+ content-disposition "0.5.4"
+ content-type "~1.0.4"
+ cookie "0.5.0"
+ cookie-signature "1.0.6"
+ debug "2.6.9"
+ depd "2.0.0"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ finalhandler "1.2.0"
+ fresh "0.5.2"
+ http-errors "2.0.0"
+ merge-descriptors "1.0.1"
+ methods "~1.1.2"
+ on-finished "2.4.1"
+ parseurl "~1.3.3"
+ path-to-regexp "0.1.7"
+ proxy-addr "~2.0.7"
+ qs "6.11.0"
+ range-parser "~1.2.1"
+ safe-buffer "5.2.1"
+ send "0.18.0"
+ serve-static "1.15.0"
+ setprototypeof "1.2.0"
+ statuses "2.0.1"
+ type-is "~1.6.18"
+ utils-merge "1.0.1"
+ vary "~1.1.2"
+
+extend@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
+ integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
+
+external-editor@^3.0.3:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
+ integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
+ dependencies:
+ chardet "^0.7.0"
+ iconv-lite "^0.4.24"
+ tmp "^0.0.33"
+
+extract-zip@1.6.7:
+ version "1.6.7"
+ resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9"
+ integrity sha512-NWFb/0zxv3qh7f6hEy+F+Y+jPAqt1bfT52GR8Vi7sEFg2fBZlG/aM6ZrSGPUscP0I4JRhtgVG6I17HOuD7GESw==
+ dependencies:
+ concat-stream "1.6.2"
+ debug "2.6.9"
+ mkdirp "0.5.1"
+ yauzl "2.4.1"
+
+extract-zip@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
+ integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
+ dependencies:
+ debug "^4.1.1"
+ get-stream "^5.1.0"
+ yauzl "^2.10.0"
+ optionalDependencies:
+ "@types/yauzl" "^2.9.1"
+
+extsprintf@1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
+ integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==
+
+extsprintf@^1.2.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07"
+ integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==
+
+fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
+fast-glob@^3.2.5, fast-glob@^3.2.7, fast-glob@^3.2.9:
+ version "3.2.12"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
+ integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.2"
+ merge2 "^1.3.0"
+ micromatch "^4.0.4"
+
+fast-json-stable-stringify@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
+ integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+
+fast-levenshtein@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+ integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
+
+fastest-levenshtein@^1.0.12:
+ version "1.0.16"
+ resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5"
+ integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==
+
+fastq@^1.6.0:
+ version "1.13.0"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c"
+ integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==
+ dependencies:
+ reusify "^1.0.4"
+
+faye-websocket@^0.11.3:
+ version "0.11.4"
+ resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da"
+ integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==
+ dependencies:
+ websocket-driver ">=0.5.1"
+
+fd-slicer@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65"
+ integrity sha512-MX1ZLPIuKED51hrI4++K+1B0VX87Cs4EkybD2q12Ysuf5p4vkmHqMvQJRlDwROqFr4D2Pzyit5wGQxf30grIcw==
+ dependencies:
+ pend "~1.2.0"
+
+fd-slicer@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
+ integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==
+ dependencies:
+ pend "~1.2.0"
+
+figures@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
+ integrity sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==
+ dependencies:
+ escape-string-regexp "^1.0.5"
+ object-assign "^4.1.0"
+
+figures@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
+ integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==
+ dependencies:
+ escape-string-regexp "^1.0.5"
+
+figures@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
+ integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
+ dependencies:
+ escape-string-regexp "^1.0.5"
+
+file-entry-cache@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f"
+ integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==
+ dependencies:
+ flat-cache "^4.0.0"
+
+fill-range@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
+ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+filter-obj@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b"
+ integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==
+
+finalhandler@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32"
+ integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==
+ dependencies:
+ debug "2.6.9"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ on-finished "2.4.1"
+ parseurl "~1.3.3"
+ statuses "2.0.1"
+ unpipe "~1.0.0"
+
+find-cache-dir@^3.3.1:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b"
+ integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==
+ dependencies:
+ commondir "^1.0.1"
+ make-dir "^3.0.2"
+ pkg-dir "^4.1.0"
+
+find-up@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
+ integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==
+ dependencies:
+ locate-path "^2.0.0"
+
+find-up@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
+ integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
+ dependencies:
+ locate-path "^3.0.0"
+
+find-up@^4.0.0, find-up@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
+ integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+ dependencies:
+ locate-path "^5.0.0"
+ path-exists "^4.0.0"
+
+find-up@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
+ integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
+ dependencies:
+ locate-path "^6.0.0"
+ path-exists "^4.0.0"
+
+find-up@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-7.0.0.tgz#e8dec1455f74f78d888ad65bf7ca13dd2b4e66fb"
+ integrity sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==
+ dependencies:
+ locate-path "^7.2.0"
+ path-exists "^5.0.0"
+ unicorn-magic "^0.1.0"
+
+flat-cache@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c"
+ integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==
+ dependencies:
+ flatted "^3.2.9"
+ keyv "^4.5.4"
+
+flat@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
+ integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
+
+flatted@^3.2.9:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
+ integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
+
+floating-vue@^5.2.2:
+ version "5.2.2"
+ resolved "https://registry.yarnpkg.com/floating-vue/-/floating-vue-5.2.2.tgz#e263932042753f59f3e36e7c1188f3f3e272a539"
+ integrity sha512-afW+h2CFafo+7Y9Lvw/xsqjaQlKLdJV7h1fCHfcYQ1C4SVMlu7OAekqWgu5d4SgvkBVU0pVpLlVsrSTBURFRkg==
+ dependencies:
+ "@floating-ui/dom" "~1.1.1"
+ vue-resize "^2.0.0-alpha.1"
+
+focus-visible@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/focus-visible/-/focus-visible-5.2.0.tgz#3a9e41fccf587bd25dcc2ef045508284f0a4d6b3"
+ integrity sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ==
+
+follow-redirects@^1.0.0, follow-redirects@^1.14.0:
+ version "1.15.2"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
+ integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
+
+forever-agent@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
+ integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==
+
+form-data@~2.3.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
+ integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.6"
+ mime-types "^2.1.12"
+
+forwarded@0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
+ integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
+
+fresh@0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+ integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
+
+friendly-errors-webpack-plugin@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.0.tgz#efc86cbb816224565861a1be7a9d84d0aafea136"
+ integrity sha512-K27M3VK30wVoOarP651zDmb93R9zF28usW4ocaK3mfQeIEI5BPht/EzZs5E8QLLwbLRJQMwscAjDxYPb1FuNiw==
+ dependencies:
+ chalk "^1.1.3"
+ error-stack-parser "^2.0.0"
+ string-width "^2.0.0"
+
+from@~0:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
+ integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==
+
+fs-constants@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
+ integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
+
+fs-extra@5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd"
+ integrity sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==
+ dependencies:
+ graceful-fs "^4.1.2"
+ jsonfile "^4.0.0"
+ universalify "^0.1.0"
+
+fs-extra@^10.0.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
+ integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
+ dependencies:
+ graceful-fs "^4.2.0"
+ jsonfile "^6.0.1"
+ universalify "^2.0.0"
+
+fs-extra@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
+ integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
+ dependencies:
+ graceful-fs "^4.2.0"
+ jsonfile "^4.0.0"
+ universalify "^0.1.0"
+
+fs-extra@^9.1.0:
+ version "9.1.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
+ integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==
+ dependencies:
+ at-least-node "^1.0.0"
+ graceful-fs "^4.2.0"
+ jsonfile "^6.0.1"
+ universalify "^2.0.0"
+
+fs-minipass@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
+ integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
+ dependencies:
+ minipass "^2.6.0"
+
+fs-minipass@^2.0.0, fs-minipass@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
+ integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
+ dependencies:
+ minipass "^3.0.0"
+
+fs-monkey@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3"
+ integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+
+fsevents@~2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+ integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
+function-bind@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+ integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+function-bind@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
+ integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
+
+function.prototype.name@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621"
+ integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.0"
+ functions-have-names "^1.2.2"
+
+functions-have-names@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
+ integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
+
+gauge@~2.7.3:
+ version "2.7.4"
+ resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
+ integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==
+ dependencies:
+ aproba "^1.0.3"
+ console-control-strings "^1.0.0"
+ has-unicode "^2.0.0"
+ object-assign "^4.1.0"
+ signal-exit "^3.0.0"
+ string-width "^1.0.1"
+ strip-ansi "^3.0.1"
+ wide-align "^1.1.0"
+
+gensync@^1.0.0-beta.2:
+ version "1.0.0-beta.2"
+ resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
+ integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
+
+get-caller-file@^2.0.1, get-caller-file@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
+ integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+
+get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385"
+ integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==
+ dependencies:
+ function-bind "^1.1.1"
+ has "^1.0.3"
+ has-symbols "^1.0.3"
+
+get-pkg-repo@^4.0.0:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz#75973e1c8050c73f48190c52047c4cee3acbf385"
+ integrity sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==
+ dependencies:
+ "@hutson/parse-repository-url" "^3.0.0"
+ hosted-git-info "^4.0.0"
+ through2 "^2.0.0"
+ yargs "^16.2.0"
+
+get-port@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193"
+ integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==
+
+get-stream@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
+ integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==
+
+get-stream@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
+ integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
+ dependencies:
+ pump "^3.0.0"
+
+get-stream@^5.0.0, get-stream@^5.1.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
+ integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
+ dependencies:
+ pump "^3.0.0"
+
+get-stream@^6.0.0:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
+ integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
+
+get-symbol-description@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6"
+ integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.1.1"
+
+get-tsconfig@^4.7.0:
+ version "4.7.2"
+ resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.2.tgz#0dcd6fb330391d46332f4c6c1bf89a6514c2ddce"
+ integrity sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==
+ dependencies:
+ resolve-pkg-maps "^1.0.0"
+
+get-tsconfig@^4.7.3:
+ version "4.7.5"
+ resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.5.tgz#5e012498579e9a6947511ed0cd403272c7acbbaf"
+ integrity sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==
+ dependencies:
+ resolve-pkg-maps "^1.0.0"
+
+getos@3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/getos/-/getos-3.1.1.tgz#967a813cceafee0156b0483f7cffa5b3eff029c5"
+ integrity sha512-oUP1rnEhAr97rkitiszGP9EgDVYnmchgFzfqRzSkgtfv7ai6tEi7Ko8GgjNXts7VLWEqrTWyhsOKLe5C5b/Zkg==
+ dependencies:
+ async "2.6.1"
+
+getpass@^0.1.1:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
+ integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==
+ dependencies:
+ assert-plus "^1.0.0"
+
+git-raw-commits@^2.0.8:
+ version "2.0.11"
+ resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.11.tgz#bc3576638071d18655e1cc60d7f524920008d723"
+ integrity sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==
+ dependencies:
+ dargs "^7.0.0"
+ lodash "^4.17.15"
+ meow "^8.0.0"
+ split2 "^3.0.0"
+ through2 "^4.0.0"
+
+git-remote-origin-url@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f"
+ integrity sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==
+ dependencies:
+ gitconfiglocal "^1.0.0"
+ pify "^2.3.0"
+
+git-semver-tags@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-4.1.1.tgz#63191bcd809b0ec3e151ba4751c16c444e5b5780"
+ integrity sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==
+ dependencies:
+ meow "^8.0.0"
+ semver "^6.0.0"
+
+git-up@^4.0.0:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/git-up/-/git-up-4.0.5.tgz#e7bb70981a37ea2fb8fe049669800a1f9a01d759"
+ integrity sha512-YUvVDg/vX3d0syBsk/CKUTib0srcQME0JyHkL5BaYdwLsiCslPWmDSi8PUMo9pXYjrryMcmsCoCgsTpSCJEQaA==
+ dependencies:
+ is-ssh "^1.3.0"
+ parse-url "^6.0.0"
+
+git-url-parse@^11.4.4:
+ version "11.6.0"
+ resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-11.6.0.tgz#c634b8de7faa66498a2b88932df31702c67df605"
+ integrity sha512-WWUxvJs5HsyHL6L08wOusa/IXYtMuCAhrMmnTjQPpBU0TTHyDhnOATNH3xNQz7YOQUsqIIPTGr4xiVti1Hsk5g==
+ dependencies:
+ git-up "^4.0.0"
+
+gitconfiglocal@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b"
+ integrity sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==
+ dependencies:
+ ini "^1.3.2"
+
+glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+glob-parent@^6.0.1, glob-parent@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
+ integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
+ dependencies:
+ is-glob "^4.0.3"
+
+glob-to-regexp@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
+ integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
+
+glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7, glob@^7.2.0:
+ version "7.2.3"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
+ integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.1.1"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+global-agent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-3.0.0.tgz#ae7cd31bd3583b93c5a16437a1afe27cc33a1ab6"
+ integrity sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==
+ dependencies:
+ boolean "^3.0.1"
+ es6-error "^4.1.1"
+ matcher "^3.0.0"
+ roarr "^2.15.3"
+ semver "^7.3.2"
+ serialize-error "^7.0.1"
+
+global-dirs@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
+ integrity sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==
+ dependencies:
+ ini "^1.3.4"
+
+global-tunnel-ng@^2.7.1:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz#d03b5102dfde3a69914f5ee7d86761ca35d57d8f"
+ integrity sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==
+ dependencies:
+ encodeurl "^1.0.2"
+ lodash "^4.17.10"
+ npm-conf "^1.1.3"
+ tunnel "^0.0.6"
+
+globals@^11.1.0:
+ version "11.12.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
+ integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+
+globals@^13.24.0:
+ version "13.24.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171"
+ integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==
+ dependencies:
+ type-fest "^0.20.2"
+
+globals@^14.0.0:
+ version "14.0.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e"
+ integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==
+
+globals@^15.0.0, globals@^15.3.0:
+ version "15.3.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-15.3.0.tgz#619db01f88d8fb91b0ed841a820cd980299575e5"
+ integrity sha512-cCdyVjIUVTtX8ZsPkq1oCsOsLmGIswqnjZYMJJTGaNApj1yHtLSymKhwH51ttirREn75z3p4k051clwg7rvNKA==
+
+globalthis@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf"
+ integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==
+ dependencies:
+ define-properties "^1.1.3"
+
+globby@^11.0.2, globby@^11.1.0:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
+ integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
+ dependencies:
+ array-union "^2.1.0"
+ dir-glob "^3.0.1"
+ fast-glob "^3.2.9"
+ ignore "^5.2.0"
+ merge2 "^1.4.1"
+ slash "^3.0.0"
+
+got@^9.6.0:
+ version "9.6.0"
+ resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85"
+ integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==
+ dependencies:
+ "@sindresorhus/is" "^0.14.0"
+ "@szmarczak/http-timer" "^1.1.2"
+ cacheable-request "^6.0.0"
+ decompress-response "^3.3.0"
+ duplexer3 "^0.1.4"
+ get-stream "^4.1.0"
+ lowercase-keys "^1.0.1"
+ mimic-response "^1.0.1"
+ p-cancelable "^1.0.0"
+ to-readable-stream "^1.0.0"
+ url-parse-lax "^3.0.0"
+
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9:
+ version "4.2.10"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
+ integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
+
+graphemer@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
+ integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
+
+handle-thing@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e"
+ integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==
+
+handlebars@^4.7.7:
+ version "4.7.7"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1"
+ integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==
+ dependencies:
+ minimist "^1.2.5"
+ neo-async "^2.6.0"
+ source-map "^0.6.1"
+ wordwrap "^1.0.0"
+ optionalDependencies:
+ uglify-js "^3.1.4"
+
+har-schema@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
+ integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==
+
+har-validator@~5.1.0, har-validator@~5.1.3:
+ version "5.1.5"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
+ integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
+ dependencies:
+ ajv "^6.12.3"
+ har-schema "^2.0.0"
+
+hard-rejection@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"
+ integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==
+
+has-ansi@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+ integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==
+ dependencies:
+ ansi-regex "^2.0.0"
+
+has-bigints@^1.0.1, has-bigints@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
+ integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
+
+has-flag@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+ integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
+
+has-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+has-property-descriptors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861"
+ integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==
+ dependencies:
+ get-intrinsic "^1.1.1"
+
+has-symbols@^1.0.2, has-symbols@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
+ integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
+
+has-tostringtag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25"
+ integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
+ dependencies:
+ has-symbols "^1.0.2"
+
+has-unicode@^2.0.0, has-unicode@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
+ integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==
+
+has@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+ dependencies:
+ function-bind "^1.1.1"
+
+hash-sum@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04"
+ integrity sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==
+
+hash-sum@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-2.0.0.tgz#81d01bb5de8ea4a214ad5d6ead1b523460b0b45a"
+ integrity sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==
+
+hasown@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c"
+ integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==
+ dependencies:
+ function-bind "^1.1.2"
+
+hex-color-regex@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
+ integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
+
+hosted-git-info@^2.1.4:
+ version "2.8.9"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
+ integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
+
+hosted-git-info@^4.0.0, hosted-git-info@^4.0.1:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224"
+ integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==
+ dependencies:
+ lru-cache "^6.0.0"
+
+hpack.js@^2.1.6:
+ version "2.1.6"
+ resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
+ integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==
+ dependencies:
+ inherits "^2.0.1"
+ obuf "^1.0.0"
+ readable-stream "^2.0.1"
+ wbuf "^1.1.0"
+
+hsl-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e"
+ integrity sha512-M5ezZw4LzXbBKMruP+BNANf0k+19hDQMgpzBIYnya//Al+fjNct9Wf3b1WedLqdEs2hKBvxq/jh+DsHJLj0F9A==
+
+hsla-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38"
+ integrity sha512-7Wn5GMLuHBjZCb2bTmnDOycho0p/7UVaAeqXZGbHrBCl6Yd/xDhQJAXe6Ga9AXJH2I5zY1dEdYw2u1UptnSBJA==
+
+html-entities@^2.3.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46"
+ integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==
+
+html-tags@^3.1.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961"
+ integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==
+
+http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
+ integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
+
+http-deceiver@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
+ integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==
+
+http-errors@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
+ integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
+ dependencies:
+ depd "2.0.0"
+ inherits "2.0.4"
+ setprototypeof "1.2.0"
+ statuses "2.0.1"
+ toidentifier "1.0.1"
+
+http-errors@~1.6.2:
+ version "1.6.3"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
+ integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==
+ dependencies:
+ depd "~1.1.2"
+ inherits "2.0.3"
+ setprototypeof "1.1.0"
+ statuses ">= 1.4.0 < 2"
+
+http-parser-js@>=0.5.1:
+ version "0.5.8"
+ resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3"
+ integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==
+
+http-proxy-agent@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a"
+ integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==
+ dependencies:
+ "@tootallnate/once" "1"
+ agent-base "6"
+ debug "4"
+
+http-proxy-middleware@^2.0.3:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f"
+ integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==
+ dependencies:
+ "@types/http-proxy" "^1.17.8"
+ http-proxy "^1.18.1"
+ is-glob "^4.0.1"
+ is-plain-obj "^3.0.0"
+ micromatch "^4.0.2"
+
+http-proxy@^1.18.1:
+ version "1.18.1"
+ resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
+ integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==
+ dependencies:
+ eventemitter3 "^4.0.0"
+ follow-redirects "^1.0.0"
+ requires-port "^1.0.0"
+
+http-signature@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
+ integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==
+ dependencies:
+ assert-plus "^1.0.0"
+ jsprim "^1.2.2"
+ sshpk "^1.7.0"
+
+https-proxy-agent@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
+ integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
+ dependencies:
+ agent-base "6"
+ debug "4"
+
+human-signals@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
+ integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
+
+human-signals@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
+ integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
+
+humanize-ms@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
+ integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==
+ dependencies:
+ ms "^2.0.0"
+
+iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.24:
+ version "0.4.24"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+ integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3"
+
+iconv-lite@^0.6.2:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
+ integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3.0.0"
+
+icss-utils@^5.0.0, icss-utils@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae"
+ integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==
+
+ieee754@^1.1.13:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
+ integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
+
+ignore-walk@^3.0.3:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.4.tgz#c9a09f69b7c7b479a5d74ac1a3c0d4236d2a6335"
+ integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==
+ dependencies:
+ minimatch "^3.0.4"
+
+ignore@^5.0.5, ignore@^5.2.4, ignore@^5.3.1:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef"
+ integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==
+
+ignore@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
+ integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
+
+import-fresh@^3.2.1:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
+ integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
+ dependencies:
+ parent-module "^1.0.0"
+ resolve-from "^4.0.0"
+
+import-local@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4"
+ integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==
+ dependencies:
+ pkg-dir "^4.2.0"
+ resolve-cwd "^3.0.0"
+
+imurmurhash@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+ integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
+
+indent-string@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
+ integrity sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==
+ dependencies:
+ repeating "^2.0.0"
+
+indent-string@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
+ integrity sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==
+
+indent-string@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
+ integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
+
+infer-owner@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
+ integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+inherits@2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+ integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==
+
+ini@^1.3.2, ini@^1.3.4:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
+ integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
+
+init-package-json@^2.0.2:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-2.0.5.tgz#78b85f3c36014db42d8f32117252504f68022646"
+ integrity sha512-u1uGAtEFu3VA6HNl/yUWw57jmKEMx8SKOxHhxjGnOFUiIlFnohKDFg4ZrPpv9wWqk44nDxGJAtqjdQFm+9XXQA==
+ dependencies:
+ npm-package-arg "^8.1.5"
+ promzard "^0.3.0"
+ read "~1.0.1"
+ read-package-json "^4.1.1"
+ semver "^7.3.5"
+ validate-npm-package-license "^3.0.4"
+ validate-npm-package-name "^3.0.0"
+
+inquirer@^6.2.0:
+ version "6.5.2"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca"
+ integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==
+ dependencies:
+ ansi-escapes "^3.2.0"
+ chalk "^2.4.2"
+ cli-cursor "^2.1.0"
+ cli-width "^2.0.0"
+ external-editor "^3.0.3"
+ figures "^2.0.0"
+ lodash "^4.17.12"
+ mute-stream "0.0.7"
+ run-async "^2.2.0"
+ rxjs "^6.4.0"
+ string-width "^2.1.0"
+ strip-ansi "^5.1.0"
+ through "^2.3.6"
+
+inquirer@^7.3.3:
+ version "7.3.3"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003"
+ integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==
+ dependencies:
+ ansi-escapes "^4.2.1"
+ chalk "^4.1.0"
+ cli-cursor "^3.1.0"
+ cli-width "^3.0.0"
+ external-editor "^3.0.3"
+ figures "^3.0.0"
+ lodash "^4.17.19"
+ mute-stream "0.0.8"
+ run-async "^2.4.0"
+ rxjs "^6.6.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+ through "^2.3.6"
+
+internal-slot@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
+ integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==
+ dependencies:
+ get-intrinsic "^1.1.0"
+ has "^1.0.3"
+ side-channel "^1.0.4"
+
+interpret@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9"
+ integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
+
+interpret@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4"
+ integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==
+
+ip@^1.1.5:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48"
+ integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==
+
+ip@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
+ integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
+
+ipaddr.js@1.9.1:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
+ integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
+
+ipaddr.js@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0"
+ integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==
+
+is-alphabetical@^1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d"
+ integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==
+
+is-alphanumerical@^1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf"
+ integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==
+ dependencies:
+ is-alphabetical "^1.0.0"
+ is-decimal "^1.0.0"
+
+is-arrayish@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+ integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
+
+is-arrayish@^0.3.1:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
+ integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
+
+is-bigint@^1.0.1:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
+ integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==
+ dependencies:
+ has-bigints "^1.0.1"
+
+is-binary-path@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
+ integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+ dependencies:
+ binary-extensions "^2.0.0"
+
+is-boolean-object@^1.1.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719"
+ integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==
+ dependencies:
+ call-bind "^1.0.2"
+ has-tostringtag "^1.0.0"
+
+is-builtin-module@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169"
+ integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==
+ dependencies:
+ builtin-modules "^3.3.0"
+
+is-callable@^1.1.4, is-callable@^1.2.6:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
+ integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
+
+is-ci@1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c"
+ integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==
+ dependencies:
+ ci-info "^1.5.0"
+
+is-ci@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
+ integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==
+ dependencies:
+ ci-info "^2.0.0"
+
+is-color-stop@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345"
+ integrity sha512-H1U8Vz0cfXNujrJzEcvvwMDW9Ra+biSYA3ThdQvAnMLJkEHQXn6bWzLkxHtVYJ+Sdbx0b6finn3jZiaVe7MAHA==
+ dependencies:
+ css-color-names "^0.0.4"
+ hex-color-regex "^1.1.0"
+ hsl-regex "^1.0.0"
+ hsla-regex "^1.0.0"
+ rgb-regex "^1.0.1"
+ rgba-regex "^1.0.0"
+
+is-core-module@^2.13.0:
+ version "2.13.1"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384"
+ integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==
+ dependencies:
+ hasown "^2.0.0"
+
+is-core-module@^2.5.0, is-core-module@^2.9.0:
+ version "2.10.0"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed"
+ integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==
+ dependencies:
+ has "^1.0.3"
+
+is-date-object@^1.0.1:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
+ integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-decimal@^1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5"
+ integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==
+
+is-docker@^2.0.0, is-docker@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
+ integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-finite@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3"
+ integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==
+
+is-fullwidth-code-point@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+ integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==
+ dependencies:
+ number-is-nan "^1.0.0"
+
+is-fullwidth-code-point@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+ integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==
+
+is-fullwidth-code-point@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
+ integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+
+is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-hexadecimal@^1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7"
+ integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==
+
+is-installed-globally@0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80"
+ integrity sha512-ERNhMg+i/XgDwPIPF3u24qpajVreaiSuvpb1Uu0jugw7KKcxGyCX8cgp8P5fwTmAuXku6beDHHECdKArjlg7tw==
+ dependencies:
+ global-dirs "^0.1.0"
+ is-path-inside "^1.0.0"
+
+is-lambda@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5"
+ integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==
+
+is-negative-zero@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
+ integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==
+
+is-number-object@^1.0.4:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc"
+ integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-obj@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
+ integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==
+
+is-path-inside@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
+ integrity sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g==
+ dependencies:
+ path-is-inside "^1.0.1"
+
+is-path-inside@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
+ integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
+
+is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
+ integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==
+
+is-plain-obj@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
+ integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
+
+is-plain-obj@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7"
+ integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==
+
+is-plain-object@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
+ integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
+ dependencies:
+ isobject "^3.0.1"
+
+is-plain-object@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
+ integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
+
+is-promise@^2.1.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1"
+ integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==
+
+is-regex@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
+ integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
+ dependencies:
+ call-bind "^1.0.2"
+ has-tostringtag "^1.0.0"
+
+is-shared-array-buffer@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79"
+ integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==
+ dependencies:
+ call-bind "^1.0.2"
+
+is-ssh@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.4.0.tgz#4f8220601d2839d8fa624b3106f8e8884f01b8b2"
+ integrity sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==
+ dependencies:
+ protocols "^2.0.1"
+
+is-stream@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+ integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==
+
+is-stream@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
+ integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
+
+is-string@^1.0.5, is-string@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
+ integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-symbol@^1.0.2, is-symbol@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c"
+ integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==
+ dependencies:
+ has-symbols "^1.0.2"
+
+is-text-path@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e"
+ integrity sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==
+ dependencies:
+ text-extensions "^1.0.0"
+
+is-typedarray@^1.0.0, is-typedarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+ integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==
+
+is-weakref@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
+ integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==
+ dependencies:
+ call-bind "^1.0.2"
+
+is-wsl@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
+ integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
+ dependencies:
+ is-docker "^2.0.0"
+
+isarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+ integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+ integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
+
+isobject@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
+ integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
+
+isstream@~0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+ integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==
+
+jest-worker@^27.4.5:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0"
+ integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==
+ dependencies:
+ "@types/node" "*"
+ merge-stream "^2.0.0"
+ supports-color "^8.0.0"
+
+joi@^17.4.0:
+ version "17.6.1"
+ resolved "https://registry.yarnpkg.com/joi/-/joi-17.6.1.tgz#e77422f277091711599634ac39a409e599d7bdaa"
+ integrity sha512-Hl7/iBklIX345OCM1TiFSCZRVaAOLDGlWCp0Df2vWYgBgjkezaR7Kvm3joBciBHQjZj5sxXs859r6eqsRSlG8w==
+ dependencies:
+ "@hapi/hoek" "^9.0.0"
+ "@hapi/topo" "^5.0.0"
+ "@sideway/address" "^4.1.3"
+ "@sideway/formula" "^3.0.0"
+ "@sideway/pinpoint" "^2.0.0"
+
+joycon@^3.0.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03"
+ integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==
+
+js-tokens@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+js-yaml@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
+ integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
+ dependencies:
+ argparse "^2.0.1"
+
+jsbn@~0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
+ integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==
+
+jsdoc-type-pratt-parser@^4.0.0, jsdoc-type-pratt-parser@~4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz#136f0571a99c184d84ec84662c45c29ceff71114"
+ integrity sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==
+
+jsesc@^2.5.1:
+ version "2.5.2"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
+ integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+
+jsesc@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e"
+ integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==
+
+jsesc@~0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
+ integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==
+
+json-buffer@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898"
+ integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==
+
+json-buffer@3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
+ integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
+
+json-parse-better-errors@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
+ integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
+
+json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
+ integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
+
+json-schema-traverse@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+json-schema-traverse@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
+ integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+
+json-schema@0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
+ integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==
+
+json-stable-stringify-without-jsonify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+ integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
+
+json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+ integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==
+
+json5@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
+ integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
+ dependencies:
+ minimist "^1.2.0"
+
+json5@^2.1.2, json5@^2.2.0, json5@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
+ integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
+
+jsonc-eslint-parser@^2.0.4, jsonc-eslint-parser@^2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz#74ded53f9d716e8d0671bd167bf5391f452d5461"
+ integrity sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==
+ dependencies:
+ acorn "^8.5.0"
+ eslint-visitor-keys "^3.0.0"
+ espree "^9.0.0"
+ semver "^7.3.5"
+
+jsonc-parser@^3.2.0:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a"
+ integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==
+
+jsonfile@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
+ integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
+jsonfile@^6.0.1:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
+ integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
+ dependencies:
+ universalify "^2.0.0"
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
+jsonparse@^1.2.0, jsonparse@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
+ integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==
+
+jsprim@^1.2.2:
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb"
+ integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==
+ dependencies:
+ assert-plus "1.0.0"
+ extsprintf "1.3.0"
+ json-schema "0.4.0"
+ verror "1.10.0"
+
+keyv@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9"
+ integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==
+ dependencies:
+ json-buffer "3.0.0"
+
+keyv@^4.5.4:
+ version "4.5.4"
+ resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
+ integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==
+ dependencies:
+ json-buffer "3.0.1"
+
+kind-of@^6.0.2, kind-of@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
+ integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+
+klona@^2.0.4:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc"
+ integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==
+
+launch-editor-middleware@^2.2.1:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/launch-editor-middleware/-/launch-editor-middleware-2.6.0.tgz#2ba4fe4b695d7fe3d44dee86b6d46d57b8332dfd"
+ integrity sha512-K2yxgljj5TdCeRN1lBtO3/J26+AIDDDw+04y6VAiZbWcTdBwsYN6RrZBnW5DN/QiSIdKNjKdATLUUluWWFYTIA==
+ dependencies:
+ launch-editor "^2.6.0"
+
+launch-editor@^2.6.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.0.tgz#4c0c1a6ac126c572bd9ff9a30da1d2cae66defd7"
+ integrity sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==
+ dependencies:
+ picocolors "^1.0.0"
+ shell-quote "^1.7.3"
+
+lazy-ass@1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513"
+ integrity sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==
+
+lazystream@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638"
+ integrity sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==
+ dependencies:
+ readable-stream "^2.0.5"
+
+lerna@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/lerna/-/lerna-4.0.0.tgz#b139d685d50ea0ca1be87713a7c2f44a5b678e9e"
+ integrity sha512-DD/i1znurfOmNJb0OBw66NmNqiM8kF6uIrzrJ0wGE3VNdzeOhz9ziWLYiRaZDGGwgbcjOo6eIfcx9O5Qynz+kg==
+ dependencies:
+ "@lerna/add" "4.0.0"
+ "@lerna/bootstrap" "4.0.0"
+ "@lerna/changed" "4.0.0"
+ "@lerna/clean" "4.0.0"
+ "@lerna/cli" "4.0.0"
+ "@lerna/create" "4.0.0"
+ "@lerna/diff" "4.0.0"
+ "@lerna/exec" "4.0.0"
+ "@lerna/import" "4.0.0"
+ "@lerna/info" "4.0.0"
+ "@lerna/init" "4.0.0"
+ "@lerna/link" "4.0.0"
+ "@lerna/list" "4.0.0"
+ "@lerna/publish" "4.0.0"
+ "@lerna/run" "4.0.0"
+ "@lerna/version" "4.0.0"
+ import-local "^3.0.2"
+ npmlog "^4.1.2"
+
+levn@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
+ integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
+ dependencies:
+ prelude-ls "^1.2.1"
+ type-check "~0.4.0"
+
+libnpmaccess@^4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-4.0.3.tgz#dfb0e5b0a53c315a2610d300e46b4ddeb66e7eec"
+ integrity sha512-sPeTSNImksm8O2b6/pf3ikv4N567ERYEpeKRPSmqlNt1dTZbvgpJIzg5vAhXHpw2ISBsELFRelk0jEahj1c6nQ==
+ dependencies:
+ aproba "^2.0.0"
+ minipass "^3.1.1"
+ npm-package-arg "^8.1.2"
+ npm-registry-fetch "^11.0.0"
+
+libnpmpublish@^4.0.0:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-4.0.2.tgz#be77e8bf5956131bcb45e3caa6b96a842dec0794"
+ integrity sha512-+AD7A2zbVeGRCFI2aO//oUmapCwy7GHqPXFJh3qpToSRNU+tXKJ2YFUgjt04LPPAf2dlEH95s6EhIHM1J7bmOw==
+ dependencies:
+ normalize-package-data "^3.0.2"
+ npm-package-arg "^8.1.2"
+ npm-registry-fetch "^11.0.0"
+ semver "^7.1.3"
+ ssri "^8.0.1"
+
+lilconfig@^2.0.5:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4"
+ integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==
+
+lines-and-columns@^1.1.6:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
+ integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
+
+listr-silent-renderer@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e"
+ integrity sha512-L26cIFm7/oZeSNVhWB6faeorXhMg4HNlb/dS/7jHhr708jxlXrtrBWo4YUxZQkc6dGoxEAe6J/D3juTRBUzjtA==
+
+listr-update-renderer@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.2.0.tgz#ca80e1779b4e70266807e8eed1ad6abe398550f9"
+ integrity sha512-0G/CLBomVga7gpCMHw5Adg9kafRz0HDAOxa1GrWywXr1oNYRW/n4pPy7xF/hniRCLRCorZMCxaMGSmgsp1QHsA==
+ dependencies:
+ chalk "^1.1.3"
+ cli-truncate "^0.2.1"
+ elegant-spinner "^1.0.1"
+ figures "^1.7.0"
+ indent-string "^3.0.0"
+ log-symbols "^1.0.2"
+ log-update "^1.0.2"
+ strip-ansi "^3.0.1"
+
+listr-verbose-renderer@^0.4.0:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35"
+ integrity sha512-tWEhvyB9UUq+4fkEwQ2NQK2JfYhsc3slSeYRkuc9CiJ3GFMRa5CRUcmqo+IIF+L95uZqv5dzZDC6vCggC28C0g==
+ dependencies:
+ chalk "^1.1.3"
+ cli-cursor "^1.0.2"
+ date-fns "^1.27.2"
+ figures "^1.7.0"
+
+listr@0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/listr/-/listr-0.12.0.tgz#6bce2c0f5603fa49580ea17cd6a00cc0e5fa451a"
+ integrity sha512-5GlrcOoGOBd/hFSI7hMvVXb+5jFMVc17e1VQzpa7VJna1SDTYSCrCpqBQUkuWW18xibTR+PQndjVtuEBKtOWVw==
+ dependencies:
+ chalk "^1.1.3"
+ cli-truncate "^0.2.1"
+ figures "^1.7.0"
+ indent-string "^2.1.0"
+ is-promise "^2.1.0"
+ is-stream "^1.1.0"
+ listr-silent-renderer "^1.1.1"
+ listr-update-renderer "^0.2.0"
+ listr-verbose-renderer "^0.4.0"
+ log-symbols "^1.0.2"
+ log-update "^1.0.2"
+ ora "^0.2.3"
+ p-map "^1.1.1"
+ rxjs "^5.0.0-beta.11"
+ stream-to-observable "^0.1.0"
+ strip-ansi "^3.0.1"
+
+load-json-file@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
+ integrity sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==
+ dependencies:
+ graceful-fs "^4.1.2"
+ parse-json "^4.0.0"
+ pify "^3.0.0"
+ strip-bom "^3.0.0"
+
+load-json-file@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-6.2.0.tgz#5c7770b42cafa97074ca2848707c61662f4251a1"
+ integrity sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==
+ dependencies:
+ graceful-fs "^4.1.15"
+ parse-json "^5.0.0"
+ strip-bom "^4.0.0"
+ type-fest "^0.6.0"
+
+loader-runner@^4.2.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1"
+ integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==
+
+loader-utils@^1.0.2, loader-utils@^1.1.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
+ integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
+ dependencies:
+ big.js "^5.2.2"
+ emojis-list "^3.0.0"
+ json5 "^1.0.1"
+
+loader-utils@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129"
+ integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==
+ dependencies:
+ big.js "^5.2.2"
+ emojis-list "^3.0.0"
+ json5 "^2.1.2"
+
+local-pkg@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.0.tgz#093d25a346bae59a99f80e75f6e9d36d7e8c925c"
+ integrity sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==
+ dependencies:
+ mlly "^1.4.2"
+ pkg-types "^1.0.3"
+
+locate-path@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
+ integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==
+ dependencies:
+ p-locate "^2.0.0"
+ path-exists "^3.0.0"
+
+locate-path@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
+ integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
+ dependencies:
+ p-locate "^3.0.0"
+ path-exists "^3.0.0"
+
+locate-path@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
+ integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+ dependencies:
+ p-locate "^4.1.0"
+
+locate-path@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
+ integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
+ dependencies:
+ p-locate "^5.0.0"
+
+locate-path@^7.2.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.2.0.tgz#69cb1779bd90b35ab1e771e1f2f89a202c2a8a8a"
+ integrity sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==
+ dependencies:
+ p-locate "^6.0.0"
+
+lodash._reinterpolate@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
+ integrity sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==
+
+lodash.clonedeep@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
+ integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==
+
+lodash.debounce@^4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
+ integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
+
+lodash.defaults@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
+ integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==
+
+lodash.difference@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c"
+ integrity sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==
+
+lodash.flatten@^4.4.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
+ integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==
+
+lodash.ismatch@^4.4.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37"
+ integrity sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==
+
+lodash.isplainobject@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
+ integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
+
+lodash.merge@^4.6.2:
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
+ integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
+
+lodash.once@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
+ integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==
+
+lodash.template@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
+ integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==
+ dependencies:
+ lodash._reinterpolate "^3.0.0"
+ lodash.templatesettings "^4.0.0"
+
+lodash.templatesettings@^4.0.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33"
+ integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==
+ dependencies:
+ lodash._reinterpolate "^3.0.0"
+
+lodash.topath@^4.5.2:
+ version "4.5.2"
+ resolved "https://registry.yarnpkg.com/lodash.topath/-/lodash.topath-4.5.2.tgz#3616351f3bba61994a0931989660bd03254fd009"
+ integrity sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==
+
+lodash.union@^4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
+ integrity sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==
+
+lodash@4.17.15:
+ version "4.17.15"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
+ integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
+
+lodash@^4.17.10, lodash@^4.17.12, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.7.0:
+ version "4.17.21"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+ integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+
+log-symbols@2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
+ integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==
+ dependencies:
+ chalk "^2.0.1"
+
+log-symbols@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
+ integrity sha512-mmPrW0Fh2fxOzdBbFv4g1m6pR72haFLPJ2G5SJEELf1y+iaQrDG6cWCPjy54RHYbZAt7X+ls690Kw62AdWXBzQ==
+ dependencies:
+ chalk "^1.0.0"
+
+log-update@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/log-update/-/log-update-1.0.2.tgz#19929f64c4093d2d2e7075a1dad8af59c296b8d1"
+ integrity sha512-4vSow8gbiGnwdDNrpy1dyNaXWKSCIPop0EHdE8GrnngHoJujM3QhvHUN/igsYCgPoHo7pFOezlJ61Hlln0KHyA==
+ dependencies:
+ ansi-escapes "^1.0.0"
+ cli-cursor "^1.0.2"
+
+lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
+ integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==
+
+lowercase-keys@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
+ integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
+
+lru-cache@^4.1.2:
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
+ integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
+ dependencies:
+ pseudomap "^1.0.2"
+ yallist "^2.1.2"
+
+lru-cache@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
+ integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
+ dependencies:
+ yallist "^3.0.2"
+
+lru-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+ dependencies:
+ yallist "^4.0.0"
+
+magic-string@^0.25.7:
+ version "0.25.9"
+ resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
+ integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
+ dependencies:
+ sourcemap-codec "^1.4.8"
+
+magic-string@^0.30.0:
+ version "0.30.3"
+ resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.3.tgz#403755dfd9d6b398dfa40635d52e96c5ac095b85"
+ integrity sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==
+ dependencies:
+ "@jridgewell/sourcemap-codec" "^1.4.15"
+
+make-dir@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
+ integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
+ dependencies:
+ pify "^4.0.1"
+ semver "^5.6.0"
+
+make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
+ integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
+ dependencies:
+ semver "^6.0.0"
+
+make-fetch-happen@^8.0.9:
+ version "8.0.14"
+ resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz#aaba73ae0ab5586ad8eaa68bd83332669393e222"
+ integrity sha512-EsS89h6l4vbfJEtBZnENTOFk8mCRpY5ru36Xe5bcX1KYIli2mkSHqoFsp5O1wMDvTJJzxe/4THpCTtygjeeGWQ==
+ dependencies:
+ agentkeepalive "^4.1.3"
+ cacache "^15.0.5"
+ http-cache-semantics "^4.1.0"
+ http-proxy-agent "^4.0.1"
+ https-proxy-agent "^5.0.0"
+ is-lambda "^1.0.1"
+ lru-cache "^6.0.0"
+ minipass "^3.1.3"
+ minipass-collect "^1.0.2"
+ minipass-fetch "^1.3.2"
+ minipass-flush "^1.0.5"
+ minipass-pipeline "^1.2.4"
+ promise-retry "^2.0.1"
+ socks-proxy-agent "^5.0.0"
+ ssri "^8.0.0"
+
+make-fetch-happen@^9.0.1:
+ version "9.1.0"
+ resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968"
+ integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==
+ dependencies:
+ agentkeepalive "^4.1.3"
+ cacache "^15.2.0"
+ http-cache-semantics "^4.1.0"
+ http-proxy-agent "^4.0.1"
+ https-proxy-agent "^5.0.0"
+ is-lambda "^1.0.1"
+ lru-cache "^6.0.0"
+ minipass "^3.1.3"
+ minipass-collect "^1.0.2"
+ minipass-fetch "^1.3.2"
+ minipass-flush "^1.0.5"
+ minipass-pipeline "^1.2.4"
+ negotiator "^0.6.2"
+ promise-retry "^2.0.1"
+ socks-proxy-agent "^6.0.0"
+ ssri "^8.0.0"
+
+map-obj@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
+ integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==
+
+map-obj@^4.0.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a"
+ integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==
+
+map-stream@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
+ integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==
+
+matcher@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca"
+ integrity sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==
+ dependencies:
+ escape-string-regexp "^4.0.0"
+
+mdast-util-from-markdown@^0.8.5:
+ version "0.8.5"
+ resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz#d1ef2ca42bc377ecb0463a987910dae89bd9a28c"
+ integrity sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==
+ dependencies:
+ "@types/mdast" "^3.0.0"
+ mdast-util-to-string "^2.0.0"
+ micromark "~2.11.0"
+ parse-entities "^2.0.0"
+ unist-util-stringify-position "^2.0.0"
+
+mdast-util-to-string@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b"
+ integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==
+
+media-typer@0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+ integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
+
+memfs@^3.4.3:
+ version "3.4.7"
+ resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.7.tgz#e5252ad2242a724f938cb937e3c4f7ceb1f70e5a"
+ integrity sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw==
+ dependencies:
+ fs-monkey "^1.0.3"
+
+meow@^8.0.0:
+ version "8.1.2"
+ resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897"
+ integrity sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==
+ dependencies:
+ "@types/minimist" "^1.2.0"
+ camelcase-keys "^6.2.2"
+ decamelize-keys "^1.1.0"
+ hard-rejection "^2.1.0"
+ minimist-options "4.1.0"
+ normalize-package-data "^3.0.0"
+ read-pkg-up "^7.0.1"
+ redent "^3.0.0"
+ trim-newlines "^3.0.0"
+ type-fest "^0.18.0"
+ yargs-parser "^20.2.3"
+
+merge-descriptors@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+ integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
+
+merge-source-map@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646"
+ integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==
+ dependencies:
+ source-map "^0.6.1"
+
+merge-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
+ integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
+
+merge2@^1.3.0, merge2@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+methods@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+ integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
+
+micromark@~2.11.0:
+ version "2.11.4"
+ resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a"
+ integrity sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==
+ dependencies:
+ debug "^4.0.0"
+ parse-entities "^2.0.0"
+
+micromatch@^4.0.2, micromatch@^4.0.4:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
+ integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
+ dependencies:
+ braces "^3.0.2"
+ picomatch "^2.3.1"
+
+mime-db@1.52.0, "mime-db@>= 1.43.0 < 2":
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34:
+ version "2.1.35"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
+mime@1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+ integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
+
+mimic-fn@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
+ integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
+
+mimic-fn@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+ integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+
+mimic-response@^1.0.0, mimic-response@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
+ integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
+
+min-indent@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
+ integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
+
+mini-css-extract-plugin@^1.5.0:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz#83172b4fd812f8fc4a09d6f6d16f924f53990ca8"
+ integrity sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q==
+ dependencies:
+ loader-utils "^2.0.0"
+ schema-utils "^3.0.0"
+ webpack-sources "^1.1.0"
+
+minimalistic-assert@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
+ integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
+
+minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
+ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimatch@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7"
+ integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==
+ dependencies:
+ brace-expansion "^2.0.1"
+
+minimatch@^9.0.0, minimatch@^9.0.4:
+ version "9.0.4"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51"
+ integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==
+ dependencies:
+ brace-expansion "^2.0.1"
+
+minimatch@^9.0.3:
+ version "9.0.3"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
+ integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
+ dependencies:
+ brace-expansion "^2.0.1"
+
+minimist-options@4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619"
+ integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==
+ dependencies:
+ arrify "^1.0.1"
+ is-plain-obj "^1.1.0"
+ kind-of "^6.0.3"
+
+minimist@0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+ integrity sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==
+
+minimist@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+ integrity sha512-7Wl+Jz+IGWuSdgsQEJ4JunV0si/iMhg42MnQQG6h1R6TNeVenp4U9x5CC5v/gYqz/fENLQITAWXidNtVL0NNbw==
+
+minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
+ version "1.2.6"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
+ integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
+
+minipass-collect@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617"
+ integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==
+ dependencies:
+ minipass "^3.0.0"
+
+minipass-fetch@^1.3.0, minipass-fetch@^1.3.2:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.4.1.tgz#d75e0091daac1b0ffd7e9d41629faff7d0c1f1b6"
+ integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==
+ dependencies:
+ minipass "^3.1.0"
+ minipass-sized "^1.0.3"
+ minizlib "^2.0.0"
+ optionalDependencies:
+ encoding "^0.1.12"
+
+minipass-flush@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373"
+ integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==
+ dependencies:
+ minipass "^3.0.0"
+
+minipass-json-stream@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz#7edbb92588fbfc2ff1db2fc10397acb7b6b44aa7"
+ integrity sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==
+ dependencies:
+ jsonparse "^1.3.1"
+ minipass "^3.0.0"
+
+minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c"
+ integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==
+ dependencies:
+ minipass "^3.0.0"
+
+minipass-sized@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70"
+ integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==
+ dependencies:
+ minipass "^3.0.0"
+
+minipass@^2.6.0, minipass@^2.9.0:
+ version "2.9.0"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
+ integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
+ dependencies:
+ safe-buffer "^5.1.2"
+ yallist "^3.0.0"
+
+minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3:
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.4.tgz#ca99f95dd77c43c7a76bf51e6d200025eee0ffae"
+ integrity sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==
+ dependencies:
+ yallist "^4.0.0"
+
+minizlib@^1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
+ integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
+ dependencies:
+ minipass "^2.9.0"
+
+minizlib@^2.0.0, minizlib@^2.1.1:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
+ integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
+ dependencies:
+ minipass "^3.0.0"
+ yallist "^4.0.0"
+
+mitt@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/mitt/-/mitt-2.1.0.tgz#f740577c23176c6205b121b2973514eade1b2230"
+ integrity sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==
+
+mkdirp-infer-owner@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz#55d3b368e7d89065c38f32fd38e638f0ab61d316"
+ integrity sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw==
+ dependencies:
+ chownr "^2.0.0"
+ infer-owner "^1.0.4"
+ mkdirp "^1.0.3"
+
+mkdirp@0.5.1:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+ integrity sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==
+ dependencies:
+ minimist "0.0.8"
+
+mkdirp@^0.5.1, mkdirp@^0.5.5:
+ version "0.5.6"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
+ integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
+ dependencies:
+ minimist "^1.2.6"
+
+mkdirp@^1.0.3, mkdirp@^1.0.4, mkdirp@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
+ integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
+
+mlly@^1.2.0, mlly@^1.4.2:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.5.0.tgz#8428a4617d54cc083d3009030ac79739a0e5447a"
+ integrity sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==
+ dependencies:
+ acorn "^8.11.3"
+ pathe "^1.1.2"
+ pkg-types "^1.0.3"
+ ufo "^1.3.2"
+
+modern-normalize@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/modern-normalize/-/modern-normalize-1.1.0.tgz#da8e80140d9221426bd4f725c6e11283d34f90b7"
+ integrity sha512-2lMlY1Yc1+CUy0gw4H95uNN7vjbpoED7NNRSBHE25nWfLBdmMzFCsPshlzbxHz+gYMcBEUN8V4pU16prcdPSgA==
+
+modify-values@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
+ integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
+
+moment@2.24.0:
+ version "2.24.0"
+ resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
+ integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
+
+monaco-editor-webpack-plugin@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-3.1.0.tgz#972efc47a91b3bf3bd977885684a3180eb8f341b"
+ integrity sha512-TP5NkCAV0OeFTry5k/d60KR7CkhTXL4kgJKtE3BzjgbDb5TGEPEhoKmHBrSa6r7Oc0sNbPLZhKD/TP2ig7A+/A==
+ dependencies:
+ loader-utils "^2.0.0"
+
+monaco-editor@^0.24.0:
+ version "0.24.0"
+ resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.24.0.tgz#990b55096bcc95d08d8d28e55264c6eb17707269"
+ integrity sha512-o1f0Lz6ABFNTtnEqqqvlY9qzNx24rQZx1RgYNQ8SkWkE+Ka63keHH/RqxQ4QhN4fs/UYOnvAtEUZsPrzccH++A==
+
+ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+ integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
+
+ms@2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+ms@2.1.3, ms@^2.0.0, ms@^2.1.1:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
+ integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+
+multicast-dns@^7.2.5:
+ version "7.2.5"
+ resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced"
+ integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==
+ dependencies:
+ dns-packet "^5.2.2"
+ thunky "^1.0.2"
+
+multimatch@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-5.0.0.tgz#932b800963cea7a31a033328fa1e0c3a1874dbe6"
+ integrity sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==
+ dependencies:
+ "@types/minimatch" "^3.0.3"
+ array-differ "^3.0.0"
+ array-union "^2.1.0"
+ arrify "^2.0.1"
+ minimatch "^3.0.4"
+
+mute-stream@0.0.7:
+ version "0.0.7"
+ resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
+ integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==
+
+mute-stream@0.0.8, mute-stream@~0.0.4:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
+ integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
+
+nanoid@^3.3.4:
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
+ integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
+
+natural-compare-lite@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4"
+ integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==
+
+natural-compare@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+ integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
+
+negotiator@0.6.3, negotiator@^0.6.2:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
+ integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
+
+neo-async@^2.6.0, neo-async@^2.6.2:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
+ integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
+
+nice-try@^1.0.4:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
+ integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+
+node-emoji@^1.11.0:
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c"
+ integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==
+ dependencies:
+ lodash "^4.17.21"
+
+node-fetch@^2.6.1, node-fetch@^2.6.7:
+ version "2.6.7"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
+ integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
+ dependencies:
+ whatwg-url "^5.0.0"
+
+node-forge@^1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
+ integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
+
+node-gyp-build@^4.3.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40"
+ integrity sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==
+
+node-gyp@^5.0.2:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.1.1.tgz#eb915f7b631c937d282e33aed44cb7a025f62a3e"
+ integrity sha512-WH0WKGi+a4i4DUt2mHnvocex/xPLp9pYt5R6M2JdFB7pJ7Z34hveZ4nDTGTiLXCkitA9T8HFZjhinBCiVHYcWw==
+ dependencies:
+ env-paths "^2.2.0"
+ glob "^7.1.4"
+ graceful-fs "^4.2.2"
+ mkdirp "^0.5.1"
+ nopt "^4.0.1"
+ npmlog "^4.1.2"
+ request "^2.88.0"
+ rimraf "^2.6.3"
+ semver "^5.7.1"
+ tar "^4.4.12"
+ which "^1.3.1"
+
+node-gyp@^7.1.0:
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.2.tgz#21a810aebb187120251c3bcec979af1587b188ae"
+ integrity sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==
+ dependencies:
+ env-paths "^2.2.0"
+ glob "^7.1.4"
+ graceful-fs "^4.2.3"
+ nopt "^5.0.0"
+ npmlog "^4.1.2"
+ request "^2.88.2"
+ rimraf "^3.0.2"
+ semver "^7.3.2"
+ tar "^6.0.2"
+ which "^2.0.2"
+
+node-releases@^2.0.14:
+ version "2.0.14"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b"
+ integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==
+
+node-releases@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503"
+ integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==
+
+nopt@^4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
+ integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==
+ dependencies:
+ abbrev "1"
+ osenv "^0.1.4"
+
+nopt@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
+ integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==
+ dependencies:
+ abbrev "1"
+
+normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
+ integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
+ dependencies:
+ hosted-git-info "^2.1.4"
+ resolve "^1.10.0"
+ semver "2 || 3 || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+
+normalize-package-data@^3.0.0, normalize-package-data@^3.0.2:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e"
+ integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==
+ dependencies:
+ hosted-git-info "^4.0.1"
+ is-core-module "^2.5.0"
+ semver "^7.3.4"
+ validate-npm-package-license "^3.0.1"
+
+normalize-path@^3.0.0, normalize-path@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+normalize-range@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
+ integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
+
+normalize-url@^4.1.0:
+ version "4.5.1"
+ resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a"
+ integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==
+
+normalize-url@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
+ integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
+
+npm-bundled@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1"
+ integrity sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==
+ dependencies:
+ npm-normalize-package-bin "^1.0.1"
+
+npm-conf@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9"
+ integrity sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==
+ dependencies:
+ config-chain "^1.1.11"
+ pify "^3.0.0"
+
+npm-install-checks@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-4.0.0.tgz#a37facc763a2fde0497ef2c6d0ac7c3fbe00d7b4"
+ integrity sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==
+ dependencies:
+ semver "^7.1.1"
+
+npm-lifecycle@^3.1.5:
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-3.1.5.tgz#9882d3642b8c82c815782a12e6a1bfeed0026309"
+ integrity sha512-lDLVkjfZmvmfvpvBzA4vzee9cn+Me4orq0QF8glbswJVEbIcSNWib7qGOffolysc3teCqbbPZZkzbr3GQZTL1g==
+ dependencies:
+ byline "^5.0.0"
+ graceful-fs "^4.1.15"
+ node-gyp "^5.0.2"
+ resolve-from "^4.0.0"
+ slide "^1.1.6"
+ uid-number "0.0.6"
+ umask "^1.1.0"
+ which "^1.3.1"
+
+npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2"
+ integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==
+
+npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-package-arg@^8.1.0, npm-package-arg@^8.1.2, npm-package-arg@^8.1.5:
+ version "8.1.5"
+ resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-8.1.5.tgz#3369b2d5fe8fdc674baa7f1786514ddc15466e44"
+ integrity sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==
+ dependencies:
+ hosted-git-info "^4.0.1"
+ semver "^7.3.4"
+ validate-npm-package-name "^3.0.0"
+
+npm-packlist@^2.1.4:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-2.2.2.tgz#076b97293fa620f632833186a7a8f65aaa6148c8"
+ integrity sha512-Jt01acDvJRhJGthnUJVF/w6gumWOZxO7IkpY/lsX9//zqQgnF7OJaxgQXcerd4uQOLu7W5bkb4mChL9mdfm+Zg==
+ dependencies:
+ glob "^7.1.6"
+ ignore-walk "^3.0.3"
+ npm-bundled "^1.1.1"
+ npm-normalize-package-bin "^1.0.1"
+
+npm-pick-manifest@^6.0.0, npm-pick-manifest@^6.1.1:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz#7b5484ca2c908565f43b7f27644f36bb816f5148"
+ integrity sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==
+ dependencies:
+ npm-install-checks "^4.0.0"
+ npm-normalize-package-bin "^1.0.1"
+ npm-package-arg "^8.1.2"
+ semver "^7.3.4"
+
+npm-registry-fetch@^11.0.0:
+ version "11.0.0"
+ resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz#68c1bb810c46542760d62a6a965f85a702d43a76"
+ integrity sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA==
+ dependencies:
+ make-fetch-happen "^9.0.1"
+ minipass "^3.1.3"
+ minipass-fetch "^1.3.0"
+ minipass-json-stream "^1.0.1"
+ minizlib "^2.0.0"
+ npm-package-arg "^8.0.0"
+
+npm-registry-fetch@^9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-9.0.0.tgz#86f3feb4ce00313bc0b8f1f8f69daae6face1661"
+ integrity sha512-PuFYYtnQ8IyVl6ib9d3PepeehcUeHN9IO5N/iCRhyg9tStQcqGQBRVHmfmMWPDERU3KwZoHFvbJ4FPXPspvzbA==
+ dependencies:
+ "@npmcli/ci-detect" "^1.0.0"
+ lru-cache "^6.0.0"
+ make-fetch-happen "^8.0.9"
+ minipass "^3.1.3"
+ minipass-fetch "^1.3.0"
+ minipass-json-stream "^1.0.1"
+ minizlib "^2.0.0"
+ npm-package-arg "^8.0.0"
+
+npm-run-path@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
+ integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==
+ dependencies:
+ path-key "^2.0.0"
+
+npm-run-path@^4.0.0, npm-run-path@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
+ integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
+ dependencies:
+ path-key "^3.0.0"
+
+npmlog@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
+ integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
+ dependencies:
+ are-we-there-yet "~1.1.2"
+ console-control-strings "~1.1.0"
+ gauge "~2.7.3"
+ set-blocking "~2.0.0"
+
+nth-check@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
+ integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==
+ dependencies:
+ boolbase "^1.0.0"
+
+num2fraction@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
+ integrity sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==
+
+number-is-nan@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+ integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==
+
+oauth-sign@~0.9.0:
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
+ integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
+
+object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+ integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
+
+object-hash@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
+ integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
+
+object-inspect@^1.12.2, object-inspect@^1.9.0:
+ version "1.12.2"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
+ integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
+
+object-keys@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
+ integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
+
+object.assign@^4.1.0, object.assign@^4.1.4:
+ version "4.1.4"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f"
+ integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ has-symbols "^1.0.3"
+ object-keys "^1.1.1"
+
+object.getownpropertydescriptors@^2.0.3:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.4.tgz#7965e6437a57278b587383831a9b829455a4bc37"
+ integrity sha512-sccv3L/pMModT6dJAYF3fzGMVcb38ysQ0tEE6ixv2yXJDtEIPph268OlAdJj5/qZMZDq2g/jqvwppt36uS/uQQ==
+ dependencies:
+ array.prototype.reduce "^1.0.4"
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.1"
+
+obuf@^1.0.0, obuf@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
+ integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
+
+on-finished@2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
+ integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
+ dependencies:
+ ee-first "1.1.1"
+
+on-headers@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
+ integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
+
+once@^1.3.0, once@^1.3.1, once@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
+ dependencies:
+ wrappy "1"
+
+onetime@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
+ integrity sha512-GZ+g4jayMqzCRMgB2sol7GiCLjKfS1PINkjmx8spcKce1LiVqcbQreXwqs2YAFXC6R03VIG28ZS31t8M866v6A==
+
+onetime@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
+ integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==
+ dependencies:
+ mimic-fn "^1.0.0"
+
+onetime@^5.1.0, onetime@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
+ integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
+ dependencies:
+ mimic-fn "^2.1.0"
+
+open@^8.0.9:
+ version "8.4.0"
+ resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8"
+ integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==
+ dependencies:
+ define-lazy-prop "^2.0.0"
+ is-docker "^2.1.1"
+ is-wsl "^2.2.0"
+
+optionator@^0.9.3:
+ version "0.9.3"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64"
+ integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==
+ dependencies:
+ "@aashutoshrathi/word-wrap" "^1.2.3"
+ deep-is "^0.1.3"
+ fast-levenshtein "^2.0.6"
+ levn "^0.4.1"
+ prelude-ls "^1.2.1"
+ type-check "^0.4.0"
+
+ora@^0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4"
+ integrity sha512-MYGyg17e2GcoDlFrAP39zu4nrAQ+STzl4fosWjR8vAlT0a2wKuuAGZTecffdVLPsnEfxXVlrUcDZ1DU5skr+QQ==
+ dependencies:
+ chalk "^1.1.1"
+ cli-cursor "^1.0.2"
+ cli-spinners "^0.1.2"
+ object-assign "^4.0.1"
+
+os-homedir@^1.0.0, os-homedir@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+ integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==
+
+os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+ integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
+
+osenv@^0.1.4:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
+ integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
+ dependencies:
+ os-homedir "^1.0.0"
+ os-tmpdir "^1.0.0"
+
+p-cancelable@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
+ integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==
+
+p-finally@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
+ integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==
+
+p-limit@^1.1.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
+ integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==
+ dependencies:
+ p-try "^1.0.0"
+
+p-limit@^2.0.0, p-limit@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
+ integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+ dependencies:
+ p-try "^2.0.0"
+
+p-limit@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+ integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+ dependencies:
+ yocto-queue "^0.1.0"
+
+p-limit@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644"
+ integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==
+ dependencies:
+ yocto-queue "^1.0.0"
+
+p-locate@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
+ integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==
+ dependencies:
+ p-limit "^1.1.0"
+
+p-locate@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
+ integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
+ dependencies:
+ p-limit "^2.0.0"
+
+p-locate@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
+ integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+ dependencies:
+ p-limit "^2.2.0"
+
+p-locate@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
+ integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
+ dependencies:
+ p-limit "^3.0.2"
+
+p-locate@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f"
+ integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==
+ dependencies:
+ p-limit "^4.0.0"
+
+p-map-series@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-2.1.0.tgz#7560d4c452d9da0c07e692fdbfe6e2c81a2a91f2"
+ integrity sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==
+
+p-map@^1.1.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b"
+ integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==
+
+p-map@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
+ integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
+ dependencies:
+ aggregate-error "^3.0.0"
+
+p-pipe@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-3.1.0.tgz#48b57c922aa2e1af6a6404cb7c6bf0eb9cc8e60e"
+ integrity sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==
+
+p-queue@^6.6.2:
+ version "6.6.2"
+ resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426"
+ integrity sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==
+ dependencies:
+ eventemitter3 "^4.0.4"
+ p-timeout "^3.2.0"
+
+p-reduce@^2.0.0, p-reduce@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-2.1.0.tgz#09408da49507c6c274faa31f28df334bc712b64a"
+ integrity sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==
+
+p-retry@^4.5.0:
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16"
+ integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==
+ dependencies:
+ "@types/retry" "0.12.0"
+ retry "^0.13.1"
+
+p-timeout@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe"
+ integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==
+ dependencies:
+ p-finally "^1.0.0"
+
+p-try@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
+ integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==
+
+p-try@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+p-waterfall@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/p-waterfall/-/p-waterfall-2.1.1.tgz#63153a774f472ccdc4eb281cdb2967fcf158b2ee"
+ integrity sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw==
+ dependencies:
+ p-reduce "^2.0.0"
+
+pacote@^11.2.6:
+ version "11.3.5"
+ resolved "https://registry.yarnpkg.com/pacote/-/pacote-11.3.5.tgz#73cf1fc3772b533f575e39efa96c50be8c3dc9d2"
+ integrity sha512-fT375Yczn4zi+6Hkk2TBe1x1sP8FgFsEIZ2/iWaXY2r/NkhDJfxbcn5paz1+RTFCyNf+dPnaoBDJoAxXSU8Bkg==
+ dependencies:
+ "@npmcli/git" "^2.1.0"
+ "@npmcli/installed-package-contents" "^1.0.6"
+ "@npmcli/promise-spawn" "^1.2.0"
+ "@npmcli/run-script" "^1.8.2"
+ cacache "^15.0.5"
+ chownr "^2.0.0"
+ fs-minipass "^2.1.0"
+ infer-owner "^1.0.4"
+ minipass "^3.1.3"
+ mkdirp "^1.0.3"
+ npm-package-arg "^8.0.1"
+ npm-packlist "^2.1.4"
+ npm-pick-manifest "^6.0.0"
+ npm-registry-fetch "^11.0.0"
+ promise-retry "^2.0.1"
+ read-package-json-fast "^2.0.1"
+ rimraf "^3.0.2"
+ ssri "^8.0.1"
+ tar "^6.1.0"
+
+parent-module@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
+ integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
+ dependencies:
+ callsites "^3.0.0"
+
+parse-entities@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8"
+ integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==
+ dependencies:
+ character-entities "^1.0.0"
+ character-entities-legacy "^1.0.0"
+ character-reference-invalid "^1.0.0"
+ is-alphanumerical "^1.0.0"
+ is-decimal "^1.0.0"
+ is-hexadecimal "^1.0.0"
+
+parse-gitignore@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/parse-gitignore/-/parse-gitignore-2.0.0.tgz#81156b265115c507129f3faea067b8476da3b642"
+ integrity sha512-RmVuCHWsfu0QPNW+mraxh/xjQVw/lhUCUru8Zni3Ctq3AoMhpDTq0OVdKS6iesd6Kqb7viCV3isAL43dciOSog==
+
+parse-json@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
+ integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==
+ dependencies:
+ error-ex "^1.3.1"
+ json-parse-better-errors "^1.0.1"
+
+parse-json@^5.0.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
+ integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
+ 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"
+
+parse-path@^4.0.0:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.4.tgz#4bf424e6b743fb080831f03b536af9fc43f0ffea"
+ integrity sha512-Z2lWUis7jlmXC1jeOG9giRO2+FsuyNipeQ43HAjqAZjwSe3SEf+q/84FGPHoso3kyntbxa4c4i77t3m6fGf8cw==
+ dependencies:
+ is-ssh "^1.3.0"
+ protocols "^1.4.0"
+ qs "^6.9.4"
+ query-string "^6.13.8"
+
+parse-url@^6.0.0:
+ version "6.0.5"
+ resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-6.0.5.tgz#4acab8982cef1846a0f8675fa686cef24b2f6f9b"
+ integrity sha512-e35AeLTSIlkw/5GFq70IN7po8fmDUjpDPY1rIK+VubRfsUvBonjQ+PBZG+vWMACnQSmNlvl524IucoDmcioMxA==
+ dependencies:
+ is-ssh "^1.3.0"
+ normalize-url "^6.1.0"
+ parse-path "^4.0.0"
+ protocols "^1.4.0"
+
+parseurl@~1.3.2, parseurl@~1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
+ integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
+
+path-browserify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd"
+ integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==
+
+path-exists@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+ integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==
+
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
+path-exists@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7"
+ integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
+
+path-is-inside@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+ integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==
+
+path-key@^2.0.0, path-key@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
+ integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==
+
+path-key@^3.0.0, path-key@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
+ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+path-to-regexp@0.1.7:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+ integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
+
+path-type@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
+ integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
+ dependencies:
+ pify "^3.0.0"
+
+path-type@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
+ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
+pathe@^1.1.0, pathe@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec"
+ integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==
+
+pause-stream@0.0.11:
+ version "0.0.11"
+ resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
+ integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==
+ dependencies:
+ through "~2.3"
+
+pend@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
+ integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==
+
+performance-now@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
+ integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==
+
+picocolors@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f"
+ integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==
+
+picocolors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
+ integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
+
+picocolors@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1"
+ integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==
+
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+picomatch@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab"
+ integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==
+
+pify@^2.2.0, pify@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+ integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
+
+pify@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
+ integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==
+
+pify@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
+ integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
+
+pify@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f"
+ integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==
+
+pixi.js-legacy@^6.2.0:
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/pixi.js-legacy/-/pixi.js-legacy-6.5.4.tgz#495b94697f20160ae0f023c498816ac3f1a89542"
+ integrity sha512-1Jl8h7MDNZPQ/eb10nrmA8MR6TF8G9ibyGUXb5fpjef8IbMtu6LUFJL8pvo/yi+Kalhkcep7eV4PMbpaBYREqg==
+ dependencies:
+ "@pixi/canvas-display" "6.5.4"
+ "@pixi/canvas-extract" "6.5.4"
+ "@pixi/canvas-graphics" "6.5.4"
+ "@pixi/canvas-mesh" "6.5.4"
+ "@pixi/canvas-particle-container" "6.5.4"
+ "@pixi/canvas-prepare" "6.5.4"
+ "@pixi/canvas-renderer" "6.5.4"
+ "@pixi/canvas-sprite" "6.5.4"
+ "@pixi/canvas-sprite-tiling" "6.5.4"
+ "@pixi/canvas-text" "6.5.4"
+ pixi.js "6.5.4"
+
+pixi.js@6.5.4:
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/pixi.js/-/pixi.js-6.5.4.tgz#9289b42215ea9109924f917a333656315fb893d2"
+ integrity sha512-TbWqFN6M1ov8a14BxWn/odYeef4g/oVx4ODSm5CWZXIxrLg7d8wnEppeAA5u9hCnX/UNdtugKFLEXWDaOOg/gA==
+ dependencies:
+ "@pixi/accessibility" "6.5.4"
+ "@pixi/app" "6.5.4"
+ "@pixi/compressed-textures" "6.5.4"
+ "@pixi/constants" "6.5.4"
+ "@pixi/core" "6.5.4"
+ "@pixi/display" "6.5.4"
+ "@pixi/extensions" "6.5.4"
+ "@pixi/extract" "6.5.4"
+ "@pixi/filter-alpha" "6.5.4"
+ "@pixi/filter-blur" "6.5.4"
+ "@pixi/filter-color-matrix" "6.5.4"
+ "@pixi/filter-displacement" "6.5.4"
+ "@pixi/filter-fxaa" "6.5.4"
+ "@pixi/filter-noise" "6.5.4"
+ "@pixi/graphics" "6.5.4"
+ "@pixi/interaction" "6.5.4"
+ "@pixi/loaders" "6.5.4"
+ "@pixi/math" "6.5.4"
+ "@pixi/mesh" "6.5.4"
+ "@pixi/mesh-extras" "6.5.4"
+ "@pixi/mixin-cache-as-bitmap" "6.5.4"
+ "@pixi/mixin-get-child-by-name" "6.5.4"
+ "@pixi/mixin-get-global-position" "6.5.4"
+ "@pixi/particle-container" "6.5.4"
+ "@pixi/polyfill" "6.5.4"
+ "@pixi/prepare" "6.5.4"
+ "@pixi/runner" "6.5.4"
+ "@pixi/settings" "6.5.4"
+ "@pixi/sprite" "6.5.4"
+ "@pixi/sprite-animated" "6.5.4"
+ "@pixi/sprite-tiling" "6.5.4"
+ "@pixi/spritesheet" "6.5.4"
+ "@pixi/text" "6.5.4"
+ "@pixi/text-bitmap" "6.5.4"
+ "@pixi/ticker" "6.5.4"
+ "@pixi/utils" "6.5.4"
+
+pkg-dir@^4.1.0, pkg-dir@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
+ integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
+ dependencies:
+ find-up "^4.0.0"
+
+pkg-types@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.0.3.tgz#988b42ab19254c01614d13f4f65a2cfc7880f868"
+ integrity sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==
+ dependencies:
+ jsonc-parser "^3.2.0"
+ mlly "^1.2.0"
+ pathe "^1.1.0"
+
+pluralize@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
+ integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
+
+postcss-functions@^3:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-functions/-/postcss-functions-3.0.0.tgz#0e94d01444700a481de20de4d55fb2640564250e"
+ integrity sha512-N5yWXWKA+uhpLQ9ZhBRl2bIAdM6oVJYpDojuI1nF2SzXBimJcdjFwiAouBVbO5VuOF3qA6BSFWFc3wXbbj72XQ==
+ dependencies:
+ glob "^7.1.2"
+ object-assign "^4.1.1"
+ postcss "^6.0.9"
+ postcss-value-parser "^3.3.0"
+
+postcss-js@^2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-2.0.3.tgz#a96f0f23ff3d08cec7dc5b11bf11c5f8077cdab9"
+ integrity sha512-zS59pAk3deu6dVHyrGqmC3oDXBdNdajk4k1RyxeVXCrcEDBUBHoIhE4QTsmhxgzXxsaqFDAkUZfmMa5f/N/79w==
+ dependencies:
+ camelcase-css "^2.0.1"
+ postcss "^7.0.18"
+
+postcss-load-config@^3.1.0:
+ version "3.1.4"
+ resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855"
+ integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==
+ dependencies:
+ lilconfig "^2.0.5"
+ yaml "^1.10.2"
+
+postcss-loader@^5.2.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-5.3.0.tgz#1657f869e48d4fdb018a40771c235e499ee26244"
+ integrity sha512-/+Z1RAmssdiSLgIZwnJHwBMnlABPgF7giYzTN2NOfr9D21IJZ4mQC1R2miwp80zno9M4zMD/umGI8cR+2EL5zw==
+ dependencies:
+ cosmiconfig "^7.0.0"
+ klona "^2.0.4"
+ semver "^7.3.4"
+
+postcss-modules-extract-imports@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d"
+ integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==
+
+postcss-modules-local-by-default@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c"
+ integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==
+ dependencies:
+ icss-utils "^5.0.0"
+ postcss-selector-parser "^6.0.2"
+ postcss-value-parser "^4.1.0"
+
+postcss-modules-scope@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06"
+ integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==
+ dependencies:
+ postcss-selector-parser "^6.0.4"
+
+postcss-modules-values@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c"
+ integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==
+ dependencies:
+ icss-utils "^5.0.0"
+
+postcss-nested@^4, postcss-nested@^4.2.1:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-4.2.3.tgz#c6f255b0a720549776d220d00c4b70cd244136f6"
+ integrity sha512-rOv0W1HquRCamWy2kFl3QazJMMe1ku6rCFoAAH+9AcxdbpDeBr6k968MLWuLjvjMcGEip01ak09hKOEgpK9hvw==
+ dependencies:
+ postcss "^7.0.32"
+ postcss-selector-parser "^6.0.2"
+
+postcss-selector-parser@^6.0.15:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz#49694cb4e7c649299fea510a29fa6577104bcf53"
+ integrity sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==
+ dependencies:
+ cssesc "^3.0.0"
+ util-deprecate "^1.0.2"
+
+postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.6:
+ version "6.0.10"
+ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d"
+ integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==
+ dependencies:
+ cssesc "^3.0.0"
+ util-deprecate "^1.0.2"
+
+postcss-value-parser@^3.3.0:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
+ integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
+
+postcss-value-parser@^4.1.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
+ integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
+
+postcss@^6.0.9:
+ version "6.0.23"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
+ integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==
+ dependencies:
+ chalk "^2.4.1"
+ source-map "^0.6.1"
+ supports-color "^5.4.0"
+
+postcss@^7, postcss@^7.0.18, postcss@^7.0.32, postcss@^7.0.36:
+ version "7.0.39"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309"
+ integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==
+ dependencies:
+ picocolors "^0.2.1"
+ source-map "^0.6.1"
+
+postcss@^8.1.10, postcss@^8.2.15, postcss@^8.3.5, postcss@^8.4.13, postcss@^8.4.14:
+ version "8.4.16"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.16.tgz#33a1d675fac39941f5f445db0de4db2b6e01d43c"
+ integrity sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==
+ dependencies:
+ nanoid "^3.3.4"
+ picocolors "^1.0.0"
+ source-map-js "^1.0.2"
+
+preact@^10.0.0:
+ version "10.11.0"
+ resolved "https://registry.yarnpkg.com/preact/-/preact-10.11.0.tgz#26af45a0613f4e17a197cc39d7a1ea23e09b2532"
+ integrity sha512-Fk6+vB2kb6mSJfDgODq0YDhMfl0HNtK5+Uc9QqECO4nlyPAQwCI+BKyWO//idA7ikV7o+0Fm6LQmNuQi1wXI1w==
+
+prelude-ls@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
+ integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
+
+prepend-http@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
+ integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==
+
+"prettier@^1.18.2 || ^2.0.0":
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64"
+ integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==
+
+pretty-hrtime@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
+ integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==
+
+prismjs@^1.25.0:
+ version "1.29.0"
+ resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12"
+ integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==
+
+process-nextick-args@~2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
+ integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
+
+progress@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
+ integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
+
+promise-inflight@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
+ integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==
+
+promise-polyfill@^8.2.0:
+ version "8.2.3"
+ resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.2.3.tgz#2edc7e4b81aff781c88a0d577e5fe9da822107c6"
+ integrity sha512-Og0+jCRQetV84U8wVjMNccfGCnMQ9mGs9Hv78QFe+pSDD3gWTpz0y+1QCuxy5d/vBFuZ3iwP2eycAkvqIMPmWg==
+
+promise-retry@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22"
+ integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==
+ dependencies:
+ err-code "^2.0.2"
+ retry "^0.12.0"
+
+promzard@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee"
+ integrity sha512-JZeYqd7UAcHCwI+sTOeUDYkvEU+1bQ7iE0UT1MgB/tERkAPkesW46MrpIySzODi+owTjZtiF8Ay5j9m60KmMBw==
+ dependencies:
+ read "1"
+
+proto-list@~1.2.1:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
+ integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==
+
+protocols@^1.4.0:
+ version "1.4.8"
+ resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.8.tgz#48eea2d8f58d9644a4a32caae5d5db290a075ce8"
+ integrity sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==
+
+protocols@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/protocols/-/protocols-2.0.1.tgz#8f155da3fc0f32644e83c5782c8e8212ccf70a86"
+ integrity sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==
+
+proxy-addr@~2.0.7:
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
+ integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
+ dependencies:
+ forwarded "0.2.0"
+ ipaddr.js "1.9.1"
+
+ps-tree@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd"
+ integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==
+ dependencies:
+ event-stream "=3.3.4"
+
+pseudomap@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
+ integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==
+
+psl@^1.1.24, psl@^1.1.28:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
+ integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==
+
+pump@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
+ integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
+ dependencies:
+ end-of-stream "^1.1.0"
+ once "^1.3.1"
+
+punycode@1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
+ integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==
+
+punycode@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
+ integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==
+
+punycode@^2.1.0, punycode@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
+ integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
+
+purgecss@^4.0.3:
+ version "4.1.3"
+ resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-4.1.3.tgz#683f6a133c8c4de7aa82fe2746d1393b214918f7"
+ integrity sha512-99cKy4s+VZoXnPxaoM23e5ABcP851nC2y2GROkkjS8eJaJtlciGavd7iYAw2V84WeBqggZ12l8ef44G99HmTaw==
+ dependencies:
+ commander "^8.0.0"
+ glob "^7.1.7"
+ postcss "^8.3.5"
+ postcss-selector-parser "^6.0.6"
+
+q@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
+ integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==
+
+qs@6.10.3:
+ version "6.10.3"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e"
+ integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==
+ dependencies:
+ side-channel "^1.0.4"
+
+qs@6.11.0, qs@^6.9.4:
+ version "6.11.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
+ integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
+ dependencies:
+ side-channel "^1.0.4"
+
+qs@~6.5.2:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"
+ integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
+
+query-string@^6.13.8:
+ version "6.14.1"
+ resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.14.1.tgz#7ac2dca46da7f309449ba0f86b1fd28255b0c86a"
+ integrity sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==
+ dependencies:
+ decode-uri-component "^0.2.0"
+ filter-obj "^1.1.0"
+ split-on-first "^1.0.0"
+ strict-uri-encode "^2.0.0"
+
+querystring@0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
+ integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==
+
+queue-microtask@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+quick-lru@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
+ integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
+
+quick-lru@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
+ integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
+
+ramda@0.24.1:
+ version "0.24.1"
+ resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.24.1.tgz#c3b7755197f35b8dc3502228262c4c91ddb6b857"
+ integrity sha512-HEm619G8PaZMfkqCa23qiOe7r3R0brPu7ZgOsgKUsnvLhd0qhc/vTjkUovomgPWa5ECBa08fJZixth9LaoBo5w==
+
+randombytes@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
+ integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
+ dependencies:
+ safe-buffer "^5.1.0"
+
+range-parser@^1.2.1, range-parser@~1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
+ integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
+
+raw-body@2.5.1:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
+ integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
+ dependencies:
+ bytes "3.1.2"
+ http-errors "2.0.0"
+ iconv-lite "0.4.24"
+ unpipe "1.0.0"
+
+read-cmd-shim@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-2.0.0.tgz#4a50a71d6f0965364938e9038476f7eede3928d9"
+ integrity sha512-HJpV9bQpkl6KwjxlJcBoqu9Ba0PQg8TqSNIOrulGt54a0uup0HtevreFHzYzkm0lpnleRdNBzXznKrgxglEHQw==
+
+read-package-json-fast@^2.0.1:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz#323ca529630da82cb34b36cc0b996693c98c2b83"
+ integrity sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==
+ dependencies:
+ json-parse-even-better-errors "^2.3.0"
+ npm-normalize-package-bin "^1.0.1"
+
+read-package-json@^2.0.0:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.2.tgz#6992b2b66c7177259feb8eaac73c3acd28b9222a"
+ integrity sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==
+ dependencies:
+ glob "^7.1.1"
+ json-parse-even-better-errors "^2.3.0"
+ normalize-package-data "^2.0.0"
+ npm-normalize-package-bin "^1.0.0"
+
+read-package-json@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-3.0.1.tgz#c7108f0b9390257b08c21e3004d2404c806744b9"
+ integrity sha512-aLcPqxovhJTVJcsnROuuzQvv6oziQx4zd3JvG0vGCL5MjTONUc4uJ90zCBC6R7W7oUKBNoR/F8pkyfVwlbxqng==
+ dependencies:
+ glob "^7.1.1"
+ json-parse-even-better-errors "^2.3.0"
+ normalize-package-data "^3.0.0"
+ npm-normalize-package-bin "^1.0.0"
+
+read-package-json@^4.1.1:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-4.1.2.tgz#b444d047de7c75d4a160cb056d00c0693c1df703"
+ integrity sha512-Dqer4pqzamDE2O4M55xp1qZMuLPqi4ldk2ya648FOMHRjwMzFhuxVrG04wd0c38IsvkVdr3vgHI6z+QTPdAjrQ==
+ dependencies:
+ glob "^7.1.1"
+ json-parse-even-better-errors "^2.3.0"
+ normalize-package-data "^3.0.0"
+ npm-normalize-package-bin "^1.0.0"
+
+read-package-tree@^5.3.1:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.3.1.tgz#a32cb64c7f31eb8a6f31ef06f9cedf74068fe636"
+ integrity sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==
+ dependencies:
+ read-package-json "^2.0.0"
+ readdir-scoped-modules "^1.0.0"
+ util-promisify "^2.1.0"
+
+read-pkg-up@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
+ integrity sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==
+ dependencies:
+ find-up "^2.0.0"
+ read-pkg "^3.0.0"
+
+read-pkg-up@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507"
+ integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==
+ dependencies:
+ find-up "^4.1.0"
+ read-pkg "^5.2.0"
+ type-fest "^0.8.1"
+
+read-pkg@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
+ integrity sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==
+ dependencies:
+ load-json-file "^4.0.0"
+ normalize-package-data "^2.3.2"
+ path-type "^3.0.0"
+
+read-pkg@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237"
+ integrity sha512-+UBirHHDm5J+3WDmLBZYSklRYg82nMlz+enn+GMZ22nSR2f4bzxmhso6rzQW/3mT2PVzpzDTiYIZahk8UmZ44w==
+ dependencies:
+ normalize-package-data "^2.3.2"
+ parse-json "^4.0.0"
+ pify "^3.0.0"
+
+read-pkg@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc"
+ integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==
+ dependencies:
+ "@types/normalize-package-data" "^2.4.0"
+ normalize-package-data "^2.5.0"
+ parse-json "^5.0.0"
+ type-fest "^0.6.0"
+
+read@1, read@~1.0.1:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4"
+ integrity sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==
+ dependencies:
+ mute-stream "~0.0.4"
+
+readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
+ integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
+ dependencies:
+ inherits "^2.0.3"
+ string_decoder "^1.1.1"
+ util-deprecate "^1.0.1"
+
+readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@~2.3.6:
+ version "2.3.7"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
+ integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~2.0.0"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.1.1"
+ util-deprecate "~1.0.1"
+
+readdir-glob@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.2.tgz#b185789b8e6a43491635b6953295c5c5e3fd224c"
+ integrity sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA==
+ dependencies:
+ minimatch "^5.1.0"
+
+readdir-scoped-modules@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309"
+ integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==
+ dependencies:
+ debuglog "^1.0.1"
+ dezalgo "^1.0.0"
+ graceful-fs "^4.1.2"
+ once "^1.3.0"
+
+readdirp@~3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
+ integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+ dependencies:
+ picomatch "^2.2.1"
+
+rechoir@^0.7.0:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686"
+ integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==
+ dependencies:
+ resolve "^1.9.0"
+
+rechoir@^0.8.0:
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22"
+ integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==
+ dependencies:
+ resolve "^1.20.0"
+
+redent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f"
+ integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==
+ dependencies:
+ indent-string "^4.0.0"
+ strip-indent "^3.0.0"
+
+reduce-css-calc@^2.1.8:
+ version "2.1.8"
+ resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz#7ef8761a28d614980dc0c982f772c93f7a99de03"
+ integrity sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==
+ dependencies:
+ css-unit-converter "^1.1.1"
+ postcss-value-parser "^3.3.0"
+
+refa@^0.12.0, refa@^0.12.1:
+ version "0.12.1"
+ resolved "https://registry.yarnpkg.com/refa/-/refa-0.12.1.tgz#dac13c4782dc22b6bae6cce81a2b863888ea39c6"
+ integrity sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==
+ dependencies:
+ "@eslint-community/regexpp" "^4.8.0"
+
+regenerate-unicode-properties@^10.1.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c"
+ integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==
+ dependencies:
+ regenerate "^1.4.2"
+
+regenerate@^1.4.2:
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
+ integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
+
+regenerator-runtime@^0.13.4:
+ version "0.13.9"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
+ integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
+
+regenerator-runtime@^0.14.0:
+ version "0.14.1"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
+ integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
+
+regenerator-transform@^0.15.0:
+ version "0.15.0"
+ resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537"
+ integrity sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==
+ dependencies:
+ "@babel/runtime" "^7.8.4"
+
+regexp-ast-analysis@^0.7.0, regexp-ast-analysis@^0.7.1:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/regexp-ast-analysis/-/regexp-ast-analysis-0.7.1.tgz#c0e24cb2a90f6eadd4cbaaba129317e29d29c482"
+ integrity sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==
+ dependencies:
+ "@eslint-community/regexpp" "^4.8.0"
+ refa "^0.12.1"
+
+regexp-tree@^0.1.27:
+ version "0.1.27"
+ resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd"
+ integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==
+
+regexp.prototype.flags@^1.4.3:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac"
+ integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ functions-have-names "^1.2.2"
+
+regexpu-core@^5.1.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.1.tgz#a69c26f324c1e962e9ffd0b88b055caba8089139"
+ integrity sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ==
+ dependencies:
+ regenerate "^1.4.2"
+ regenerate-unicode-properties "^10.1.0"
+ regjsgen "^0.7.1"
+ regjsparser "^0.9.1"
+ unicode-match-property-ecmascript "^2.0.0"
+ unicode-match-property-value-ecmascript "^2.0.0"
+
+regjsgen@^0.7.1:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6"
+ integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==
+
+regjsparser@^0.10.0:
+ version "0.10.0"
+ resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.10.0.tgz#b1ed26051736b436f22fdec1c8f72635f9f44892"
+ integrity sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==
+ dependencies:
+ jsesc "~0.5.0"
+
+regjsparser@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709"
+ integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==
+ dependencies:
+ jsesc "~0.5.0"
+
+repeating@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
+ integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==
+ dependencies:
+ is-finite "^1.0.0"
+
+request-progress@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe"
+ integrity sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==
+ dependencies:
+ throttleit "^1.0.0"
+
+request@2.88.0:
+ version "2.88.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
+ integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
+ dependencies:
+ aws-sign2 "~0.7.0"
+ aws4 "^1.8.0"
+ caseless "~0.12.0"
+ combined-stream "~1.0.6"
+ extend "~3.0.2"
+ forever-agent "~0.6.1"
+ form-data "~2.3.2"
+ har-validator "~5.1.0"
+ http-signature "~1.2.0"
+ is-typedarray "~1.0.0"
+ isstream "~0.1.2"
+ json-stringify-safe "~5.0.1"
+ mime-types "~2.1.19"
+ oauth-sign "~0.9.0"
+ performance-now "^2.1.0"
+ qs "~6.5.2"
+ safe-buffer "^5.1.2"
+ tough-cookie "~2.4.3"
+ tunnel-agent "^0.6.0"
+ uuid "^3.3.2"
+
+request@^2.88.0, request@^2.88.2:
+ version "2.88.2"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
+ integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
+ dependencies:
+ aws-sign2 "~0.7.0"
+ aws4 "^1.8.0"
+ caseless "~0.12.0"
+ combined-stream "~1.0.6"
+ extend "~3.0.2"
+ forever-agent "~0.6.1"
+ form-data "~2.3.2"
+ har-validator "~5.1.3"
+ http-signature "~1.2.0"
+ is-typedarray "~1.0.0"
+ isstream "~0.1.2"
+ json-stringify-safe "~5.0.1"
+ mime-types "~2.1.19"
+ oauth-sign "~0.9.0"
+ performance-now "^2.1.0"
+ qs "~6.5.2"
+ safe-buffer "^5.1.2"
+ tough-cookie "~2.5.0"
+ tunnel-agent "^0.6.0"
+ uuid "^3.3.2"
+
+require-directory@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+ integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
+
+require-from-string@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
+ integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+
+require-main-filename@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
+ integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
+
+requires-port@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
+ integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
+
+resolve-cwd@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
+ integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==
+ dependencies:
+ resolve-from "^5.0.0"
+
+resolve-from@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
+ integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
+resolve-from@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
+ integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+
+resolve-pkg-maps@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f"
+ integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==
+
+resolve-url@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
+ integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==
+
+resolve@^1.10.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.0:
+ version "1.22.1"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
+ integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
+ dependencies:
+ is-core-module "^2.9.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+resolve@^1.22.4, resolve@^1.9.0:
+ version "1.22.8"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
+ integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
+ dependencies:
+ is-core-module "^2.13.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+responselike@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7"
+ integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==
+ dependencies:
+ lowercase-keys "^1.0.0"
+
+restore-cursor@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
+ integrity sha512-reSjH4HuiFlxlaBaFCiS6O76ZGG2ygKoSlCsipKdaZuKSPx/+bt9mULkn4l0asVzbEfQQmXRg6Wp6gv6m0wElw==
+ dependencies:
+ exit-hook "^1.0.0"
+ onetime "^1.0.0"
+
+restore-cursor@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
+ integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==
+ dependencies:
+ onetime "^2.0.0"
+ signal-exit "^3.0.2"
+
+restore-cursor@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
+ integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
+ dependencies:
+ onetime "^5.1.0"
+ signal-exit "^3.0.2"
+
+retry@^0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
+ integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==
+
+retry@^0.13.1:
+ version "0.13.1"
+ resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
+ integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==
+
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+rgb-regex@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1"
+ integrity sha512-gDK5mkALDFER2YLqH6imYvK6g02gpNGM4ILDZ472EwWfXZnC2ZEpoB2ECXTyOVUKuk/bPJZMzwQPBYICzP+D3w==
+
+rgba-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
+ integrity sha512-zgn5OjNQXLUTdq8m17KdaicF6w89TZs8ZU8y0AYENIU6wG8GG6LLm0yLSiPY8DmaYmHdgRW8rnApjoT0fQRfMg==
+
+rimraf@^2.6.3:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
+ integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
+ dependencies:
+ glob "^7.1.3"
+
+rimraf@^3.0.0, rimraf@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
+ integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
+ dependencies:
+ glob "^7.1.3"
+
+roarr@^2.15.3:
+ version "2.15.4"
+ resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.4.tgz#f5fe795b7b838ccfe35dc608e0282b9eba2e7afd"
+ integrity sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==
+ dependencies:
+ boolean "^3.0.1"
+ detect-node "^2.0.4"
+ globalthis "^1.0.1"
+ json-stringify-safe "^5.0.1"
+ semver-compare "^1.0.0"
+ sprintf-js "^1.1.2"
+
+"rollup@>=2.59.0 <2.78.0":
+ version "2.77.3"
+ resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.77.3.tgz#8f00418d3a2740036e15deb653bed1a90ee0cc12"
+ integrity sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+run-async@^2.2.0, run-async@^2.4.0:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
+ integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
+
+run-parallel@^1.1.9:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+ dependencies:
+ queue-microtask "^1.2.2"
+
+rw@1:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
+ integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==
+
+rxjs@^5.0.0-beta.11:
+ version "5.5.12"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc"
+ integrity sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==
+ dependencies:
+ symbol-observable "1.0.1"
+
+rxjs@^6.4.0, rxjs@^6.5.2, rxjs@^6.6.0:
+ version "6.6.7"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
+ integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
+ dependencies:
+ tslib "^1.9.0"
+
+rxjs@^7.1.0:
+ version "7.5.6"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.6.tgz#0446577557862afd6903517ce7cae79ecb9662bc"
+ integrity sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==
+ dependencies:
+ tslib "^2.1.0"
+
+safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+ integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
+safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+safe-regex-test@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295"
+ integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.1.3"
+ is-regex "^1.1.4"
+
+"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@^2.1.2, safer-buffer@~2.1.0:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+ integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+
+sax@~1.2.4:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+ integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
+
+schema-utils@^2.6.5, schema-utils@^2.7.0:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"
+ integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==
+ dependencies:
+ "@types/json-schema" "^7.0.5"
+ ajv "^6.12.4"
+ ajv-keywords "^3.5.2"
+
+schema-utils@^3.0.0, schema-utils@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281"
+ integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==
+ dependencies:
+ "@types/json-schema" "^7.0.8"
+ ajv "^6.12.5"
+ ajv-keywords "^3.5.2"
+
+schema-utils@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe"
+ integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==
+ dependencies:
+ "@types/json-schema" "^7.0.8"
+ ajv "^6.12.5"
+ ajv-keywords "^3.5.2"
+
+schema-utils@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7"
+ integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==
+ dependencies:
+ "@types/json-schema" "^7.0.9"
+ ajv "^8.8.0"
+ ajv-formats "^2.1.1"
+ ajv-keywords "^5.0.0"
+
+scroll-into-view-if-needed@^2.2.28:
+ version "2.2.29"
+ resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz#551791a84b7e2287706511f8c68161e4990ab885"
+ integrity sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==
+ dependencies:
+ compute-scroll-into-view "^1.0.17"
+
+scslre@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/scslre/-/scslre-0.3.0.tgz#c3211e9bfc5547fc86b1eabaa34ed1a657060155"
+ integrity sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==
+ dependencies:
+ "@eslint-community/regexpp" "^4.8.0"
+ refa "^0.12.0"
+ regexp-ast-analysis "^0.7.0"
+
+select-hose@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
+ integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==
+
+selfsigned@^2.1.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0"
+ integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==
+ dependencies:
+ "@types/node-forge" "^1.3.0"
+ node-forge "^1"
+
+semver-compare@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
+ integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==
+
+"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.1:
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
+ integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+
+semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
+ integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+
+semver@^7.1.1, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5:
+ version "7.3.7"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
+ integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
+ dependencies:
+ lru-cache "^6.0.0"
+
+semver@^7.3.6, semver@^7.5.3, semver@^7.5.4:
+ version "7.5.4"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
+ integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
+ dependencies:
+ lru-cache "^6.0.0"
+
+semver@^7.6.0, semver@^7.6.1, semver@^7.6.2:
+ version "7.6.2"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
+ integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
+
+send@0.18.0:
+ version "0.18.0"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
+ integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
+ dependencies:
+ debug "2.6.9"
+ depd "2.0.0"
+ destroy "1.2.0"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ fresh "0.5.2"
+ http-errors "2.0.0"
+ mime "1.6.0"
+ ms "2.1.3"
+ on-finished "2.4.1"
+ range-parser "~1.2.1"
+ statuses "2.0.1"
+
+serialize-error@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18"
+ integrity sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==
+ dependencies:
+ type-fest "^0.13.1"
+
+serialize-javascript@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8"
+ integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==
+ dependencies:
+ randombytes "^2.1.0"
+
+serialize-javascript@^6.0.1:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2"
+ integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==
+ dependencies:
+ randombytes "^2.1.0"
+
+serve-index@^1.9.1:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
+ integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==
+ dependencies:
+ accepts "~1.3.4"
+ batch "0.6.1"
+ debug "2.6.9"
+ escape-html "~1.0.3"
+ http-errors "~1.6.2"
+ mime-types "~2.1.17"
+ parseurl "~1.3.2"
+
+serve-static@1.15.0:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
+ integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
+ dependencies:
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ parseurl "~1.3.3"
+ send "0.18.0"
+
+set-blocking@^2.0.0, set-blocking@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
+ integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==
+
+setprototypeof@1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
+ integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
+
+setprototypeof@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
+ integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
+
+shallow-clone@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
+ integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
+ dependencies:
+ kind-of "^6.0.2"
+
+shebang-command@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
+ integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==
+ dependencies:
+ shebang-regex "^1.0.0"
+
+shebang-command@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
+ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+ dependencies:
+ shebang-regex "^3.0.0"
+
+shebang-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
+ integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==
+
+shebang-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
+ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
+shell-quote@^1.7.3:
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123"
+ integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==
+
+side-channel@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
+ integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
+ dependencies:
+ call-bind "^1.0.0"
+ get-intrinsic "^1.0.2"
+ object-inspect "^1.9.0"
+
+signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
+ integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
+
+simple-html-tokenizer@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/simple-html-tokenizer/-/simple-html-tokenizer-0.1.1.tgz#05c2eec579ffffe145a030ac26cfea61b980fabe"
+ integrity sha512-Mc/gH3RvlKvB/gkp9XwgDKEWrSYyefIJPGG8Jk1suZms/rISdUuVEMx5O1WBnTWaScvxXDvGJrZQWblUmQHjkQ==
+
+simple-swizzle@^0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
+ integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==
+ dependencies:
+ is-arrayish "^0.3.1"
+
+sisteransi@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
+ integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
+
+slash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
+slice-ansi@0.0.4:
+ version "0.0.4"
+ resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
+ integrity sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw==
+
+slide@^1.1.6:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
+ integrity sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==
+
+smart-buffer@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
+ integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
+
+socket.io-adapter@~2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz#b50a4a9ecdd00c34d4c8c808224daa1a786152a6"
+ integrity sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==
+
+socket.io-client@^4.4.1:
+ version "4.5.2"
+ resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.5.2.tgz#9481518c560388c980c88b01e3cf62f367f04c96"
+ integrity sha512-naqYfFu7CLDiQ1B7AlLhRXKX3gdeaIMfgigwavDzgJoIUYulc1qHH5+2XflTsXTPY7BlPH5rppJyUjhjrKQKLg==
+ dependencies:
+ "@socket.io/component-emitter" "~3.1.0"
+ debug "~4.3.2"
+ engine.io-client "~6.2.1"
+ socket.io-parser "~4.2.0"
+
+socket.io-parser@~4.2.0:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.1.tgz#01c96efa11ded938dcb21cbe590c26af5eff65e5"
+ integrity sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==
+ dependencies:
+ "@socket.io/component-emitter" "~3.1.0"
+ debug "~4.3.1"
+
+socket.io@^4.4.0:
+ version "4.5.2"
+ resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.5.2.tgz#1eb25fd380ab3d63470aa8279f8e48d922d443ac"
+ integrity sha512-6fCnk4ARMPZN448+SQcnn1u8OHUC72puJcNtSgg2xS34Cu7br1gQ09YKkO1PFfDn/wyUE9ZgMAwosJed003+NQ==
+ dependencies:
+ accepts "~1.3.4"
+ base64id "~2.0.0"
+ debug "~4.3.2"
+ engine.io "~6.2.0"
+ socket.io-adapter "~2.4.0"
+ socket.io-parser "~4.2.0"
+
+sockjs@^0.3.24:
+ version "0.3.24"
+ resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce"
+ integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==
+ dependencies:
+ faye-websocket "^0.11.3"
+ uuid "^8.3.2"
+ websocket-driver "^0.7.4"
+
+socks-proxy-agent@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz#032fb583048a29ebffec2e6a73fca0761f48177e"
+ integrity sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==
+ dependencies:
+ agent-base "^6.0.2"
+ debug "4"
+ socks "^2.3.3"
+
+socks-proxy-agent@^6.0.0:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz#2687a31f9d7185e38d530bef1944fe1f1496d6ce"
+ integrity sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==
+ dependencies:
+ agent-base "^6.0.2"
+ debug "^4.3.3"
+ socks "^2.6.2"
+
+socks@^2.3.3, socks@^2.6.2:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.0.tgz#f9225acdb841e874dca25f870e9130990f3913d0"
+ integrity sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==
+ dependencies:
+ ip "^2.0.0"
+ smart-buffer "^4.2.0"
+
+sort-keys@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128"
+ integrity sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==
+ dependencies:
+ is-plain-obj "^1.0.0"
+
+sort-keys@^4.0.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-4.2.0.tgz#6b7638cee42c506fff8c1cecde7376d21315be18"
+ integrity sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==
+ dependencies:
+ is-plain-obj "^2.0.0"
+
+source-list-map@^2.0.0, source-list-map@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
+ integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
+
+source-map-js@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
+ integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
+
+source-map-resolve@^0.5.2:
+ version "0.5.3"
+ resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
+ integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==
+ dependencies:
+ atob "^2.1.2"
+ decode-uri-component "^0.2.0"
+ resolve-url "^0.2.1"
+ source-map-url "^0.4.0"
+ urix "^0.1.0"
+
+source-map-support@~0.5.20:
+ version "0.5.21"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
+ integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
+ dependencies:
+ buffer-from "^1.0.0"
+ source-map "^0.6.0"
+
+source-map-url@^0.4.0:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
+ integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
+
+source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+source-map@^0.7.3:
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656"
+ integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==
+
+sourcemap-codec@^1.4.8:
+ version "1.4.8"
+ resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
+ integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
+
+spawn-command@^0.0.2-1:
+ version "0.0.2-1"
+ resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"
+ integrity sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==
+
+spdx-correct@^3.0.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
+ integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
+ dependencies:
+ spdx-expression-parse "^3.0.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-exceptions@^2.1.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
+ integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
+
+spdx-expression-parse@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
+ integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
+ dependencies:
+ spdx-exceptions "^2.1.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-expression-parse@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz#a23af9f3132115465dac215c099303e4ceac5794"
+ integrity sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==
+ dependencies:
+ spdx-exceptions "^2.1.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-license-ids@^3.0.0:
+ version "3.0.12"
+ resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779"
+ integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==
+
+spdy-transport@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31"
+ integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==
+ dependencies:
+ debug "^4.1.0"
+ detect-node "^2.0.4"
+ hpack.js "^2.1.6"
+ obuf "^1.1.2"
+ readable-stream "^3.0.6"
+ wbuf "^1.7.3"
+
+spdy@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b"
+ integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==
+ dependencies:
+ debug "^4.1.0"
+ handle-thing "^2.0.0"
+ http-deceiver "^1.2.7"
+ select-hose "^2.0.0"
+ spdy-transport "^3.0.0"
+
+speakingurl@^14.0.1:
+ version "14.0.1"
+ resolved "https://registry.yarnpkg.com/speakingurl/-/speakingurl-14.0.1.tgz#f37ec8ddc4ab98e9600c1c9ec324a8c48d772a53"
+ integrity sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==
+
+split-on-first@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
+ integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
+
+split2@^3.0.0:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f"
+ integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==
+ dependencies:
+ readable-stream "^3.0.0"
+
+split@0.3:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f"
+ integrity sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==
+ dependencies:
+ through "2"
+
+split@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9"
+ integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==
+ dependencies:
+ through "2"
+
+sprintf-js@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
+ integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
+
+sshpk@^1.7.0:
+ version "1.17.0"
+ resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5"
+ integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==
+ dependencies:
+ asn1 "~0.2.3"
+ assert-plus "^1.0.0"
+ bcrypt-pbkdf "^1.0.0"
+ dashdash "^1.12.0"
+ ecc-jsbn "~0.1.1"
+ getpass "^0.1.1"
+ jsbn "~0.1.0"
+ safer-buffer "^2.0.2"
+ tweetnacl "~0.14.0"
+
+ssri@^8.0.0, ssri@^8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af"
+ integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==
+ dependencies:
+ minipass "^3.1.1"
+
+stackframe@^1.3.4:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310"
+ integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==
+
+start-server-and-test@^1.7.1:
+ version "1.14.0"
+ resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-1.14.0.tgz#c57f04f73eac15dd51733b551d775b40837fdde3"
+ integrity sha512-on5ELuxO2K0t8EmNj9MtVlFqwBMxfWOhu4U7uZD1xccVpFlOQKR93CSe0u98iQzfNxRyaNTb/CdadbNllplTsw==
+ dependencies:
+ bluebird "3.7.2"
+ check-more-types "2.24.0"
+ debug "4.3.2"
+ execa "5.1.1"
+ lazy-ass "1.6.0"
+ ps-tree "1.2.0"
+ wait-on "6.0.0"
+
+statuses@2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
+ integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
+
+"statuses@>= 1.4.0 < 2":
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
+ integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
+
+stream-combiner@~0.0.4:
+ version "0.0.4"
+ resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14"
+ integrity sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==
+ dependencies:
+ duplexer "~0.1.1"
+
+stream-to-observable@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.1.0.tgz#45bf1d9f2d7dc09bed81f1c307c430e68b84cffe"
+ integrity sha512-h3mR71JoHxXrKApehgQk1CFbdi2nW9BAVqjPhpPD127H8iz0N61YsCLhJutm+JV0ajNAwPef0kMQsF0Jaz/A6Q==
+
+strict-uri-encode@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
+ integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==
+
+string-argv@^0.3.1:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6"
+ integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==
+
+string-width@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+ integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==
+ dependencies:
+ code-point-at "^1.0.0"
+ is-fullwidth-code-point "^1.0.0"
+ strip-ansi "^3.0.0"
+
+"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+string-width@^2.0.0, string-width@^2.1.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
+ integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
+ dependencies:
+ is-fullwidth-code-point "^2.0.0"
+ strip-ansi "^4.0.0"
+
+string-width@^3.0.0, string-width@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
+ integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
+ dependencies:
+ emoji-regex "^7.0.1"
+ is-fullwidth-code-point "^2.0.0"
+ strip-ansi "^5.1.0"
+
+string.prototype.trimend@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0"
+ integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.19.5"
+
+string.prototype.trimstart@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef"
+ integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.19.5"
+
+string_decoder@^1.1.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
+ integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
+ dependencies:
+ safe-buffer "~5.2.0"
+
+string_decoder@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+ integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
+ dependencies:
+ safe-buffer "~5.1.0"
+
+strip-ansi@^3.0.0, strip-ansi@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+ integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==
+ dependencies:
+ ansi-regex "^2.0.0"
+
+strip-ansi@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
+ integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==
+ dependencies:
+ ansi-regex "^3.0.0"
+
+strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
+ integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
+ dependencies:
+ ansi-regex "^4.1.0"
+
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+strip-bom@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+ integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
+
+strip-bom@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
+ integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==
+
+strip-eof@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
+ integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==
+
+strip-final-newline@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
+ integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
+
+strip-indent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
+ integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==
+ dependencies:
+ min-indent "^1.0.0"
+
+strip-json-comments@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
+ integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
+
+strong-log-transformer@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10"
+ integrity sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==
+ dependencies:
+ duplexer "^0.1.1"
+ minimist "^1.2.0"
+ through "^2.3.4"
+
+style-resources-loader@^1.2.1:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/style-resources-loader/-/style-resources-loader-1.5.0.tgz#6e0585ca475b9dac45387c308be90d74c814f41f"
+ integrity sha512-fIfyvQ+uvXaCBGGAgfh+9v46ARQB1AWdaop2RpQw0PBVuROsTBqGvx8dj0kxwjGOAyq3vepe4AOK3M6+Q/q2jw==
+ dependencies:
+ glob "^7.2.0"
+ loader-utils "^2.0.0"
+ schema-utils "^2.7.0"
+ tslib "^2.3.1"
+
+stylus-loader@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/stylus-loader/-/stylus-loader-3.0.2.tgz#27a706420b05a38e038e7cacb153578d450513c6"
+ integrity sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==
+ dependencies:
+ loader-utils "^1.0.2"
+ lodash.clonedeep "^4.5.0"
+ when "~3.6.x"
+
+stylus-loader@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/stylus-loader/-/stylus-loader-5.0.0.tgz#d3f548887ab67808cc40d320079c44f8ffa3d9b8"
+ integrity sha512-1OaGgixTgC8IAaMCodZXg7XYsfP1qU0UzTHDyPaWACUh34j9geJL4iA583tFJDOtfNUOfDLaBpUywc5MicQ1aA==
+ dependencies:
+ fast-glob "^3.2.5"
+ klona "^2.0.4"
+ normalize-path "^3.0.0"
+
+stylus@^0.54.5, stylus@^0.54.7:
+ version "0.54.8"
+ resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.8.tgz#3da3e65966bc567a7b044bfe0eece653e099d147"
+ integrity sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==
+ dependencies:
+ css-parse "~2.0.0"
+ debug "~3.1.0"
+ glob "^7.1.6"
+ mkdirp "~1.0.4"
+ safer-buffer "^2.1.2"
+ sax "~1.2.4"
+ semver "^6.3.0"
+ source-map "^0.7.3"
+
+sumchecker@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42"
+ integrity sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==
+ dependencies:
+ debug "^4.1.0"
+
+supports-color@5.5.0, supports-color@^5.3.0, supports-color@^5.4.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+ integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+ dependencies:
+ has-flag "^3.0.0"
+
+supports-color@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+ integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==
+
+supports-color@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
+ integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
+ dependencies:
+ has-flag "^3.0.0"
+
+supports-color@^7.1.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
+ integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-color@^8.0.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
+ integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+svg-inline-loader@^0.8.2:
+ version "0.8.2"
+ resolved "https://registry.yarnpkg.com/svg-inline-loader/-/svg-inline-loader-0.8.2.tgz#9872414f9e4141601e04eb80cda748c9a50dae71"
+ integrity sha512-kbrcEh5n5JkypaSC152eGfGcnT4lkR0eSfvefaUJkLqgGjRQJyKDvvEE/CCv5aTSdfXuc+N98w16iAojhShI3g==
+ dependencies:
+ loader-utils "^1.1.0"
+ object-assign "^4.0.1"
+ simple-html-tokenizer "^0.1.1"
+
+symbol-observable@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4"
+ integrity sha512-Kb3PrPYz4HanVF1LVGuAdW6LoVgIwjUYJGzFe7NDrBLCN4lsV/5J0MFurV+ygS4bRVwrCEt2c7MQ1R2a72oJDw==
+
+synckit@^0.6.0:
+ version "0.6.2"
+ resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.6.2.tgz#e1540b97825f2855f7170b98276e8463167f33eb"
+ integrity sha512-Vhf+bUa//YSTYKseDiiEuQmhGCoIF3CVBhunm3r/DQnYiGT4JssmnKQc44BIyOZRK2pKjXXAgbhfmbeoC9CJpA==
+ dependencies:
+ tslib "^2.3.1"
+
+tapable@^2.1.1, tapable@^2.2.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
+ integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
+
+tar-stream@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
+ integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
+ dependencies:
+ bl "^4.0.3"
+ end-of-stream "^1.4.1"
+ fs-constants "^1.0.0"
+ inherits "^2.0.3"
+ readable-stream "^3.1.1"
+
+tar@^4.4.12:
+ version "4.4.19"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3"
+ integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==
+ dependencies:
+ chownr "^1.1.4"
+ fs-minipass "^1.2.7"
+ minipass "^2.9.0"
+ minizlib "^1.3.3"
+ mkdirp "^0.5.5"
+ safe-buffer "^5.2.1"
+ yallist "^3.1.1"
+
+tar@^6.0.2, tar@^6.1.0:
+ version "6.1.11"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
+ integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
+ dependencies:
+ chownr "^2.0.0"
+ fs-minipass "^2.0.0"
+ minipass "^3.0.0"
+ minizlib "^2.1.1"
+ mkdirp "^1.0.3"
+ yallist "^4.0.0"
+
+temp-dir@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d"
+ integrity sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==
+
+temp-write@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/temp-write/-/temp-write-4.0.0.tgz#cd2e0825fc826ae72d201dc26eef3bf7e6fc9320"
+ integrity sha512-HIeWmj77uOOHb0QX7siN3OtwV3CTntquin6TNVg6SHOqCP3hYKmox90eeFOGaY1MqJ9WYDDjkyZrW6qS5AWpbw==
+ dependencies:
+ graceful-fs "^4.1.15"
+ is-stream "^2.0.0"
+ make-dir "^3.0.0"
+ temp-dir "^1.0.0"
+ uuid "^3.3.2"
+
+terser-webpack-plugin@^5.1.1:
+ version "5.3.6"
+ resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c"
+ integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==
+ dependencies:
+ "@jridgewell/trace-mapping" "^0.3.14"
+ jest-worker "^27.4.5"
+ schema-utils "^3.1.1"
+ serialize-javascript "^6.0.0"
+ terser "^5.14.1"
+
+terser-webpack-plugin@^5.3.10:
+ version "5.3.10"
+ resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199"
+ integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==
+ dependencies:
+ "@jridgewell/trace-mapping" "^0.3.20"
+ jest-worker "^27.4.5"
+ schema-utils "^3.1.1"
+ serialize-javascript "^6.0.1"
+ terser "^5.26.0"
+
+terser@^5.14.1:
+ version "5.15.0"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.0.tgz#e16967894eeba6e1091509ec83f0c60e179f2425"
+ integrity sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==
+ dependencies:
+ "@jridgewell/source-map" "^0.3.2"
+ acorn "^8.5.0"
+ commander "^2.20.0"
+ source-map-support "~0.5.20"
+
+terser@^5.26.0:
+ version "5.27.0"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-5.27.0.tgz#70108689d9ab25fef61c4e93e808e9fd092bf20c"
+ integrity sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==
+ dependencies:
+ "@jridgewell/source-map" "^0.3.3"
+ acorn "^8.8.2"
+ commander "^2.20.0"
+ source-map-support "~0.5.20"
+
+text-extensions@^1.0.0:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26"
+ integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==
+
+text-table@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+ integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
+
+throttleit@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c"
+ integrity sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==
+
+through2@^2.0.0:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
+ integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
+ dependencies:
+ readable-stream "~2.3.6"
+ xtend "~4.0.1"
+
+through2@^4.0.0:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764"
+ integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==
+ dependencies:
+ readable-stream "3"
+
+through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@~2.3, through@~2.3.1:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+ integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
+
+thunky@^1.0.2:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d"
+ integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==
+
+tinycolor2@^1.4.2:
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803"
+ integrity sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==
+
+tmp@0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877"
+ integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==
+ dependencies:
+ rimraf "^2.6.3"
+
+tmp@^0.0.33:
+ version "0.0.33"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+ integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
+ dependencies:
+ os-tmpdir "~1.0.2"
+
+tmp@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
+ integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==
+ dependencies:
+ rimraf "^3.0.0"
+
+to-fast-properties@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+ integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
+
+to-readable-stream@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771"
+ integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+toidentifier@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
+ integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
+
+toml-eslint-parser@^0.9.0, toml-eslint-parser@^0.9.3:
+ version "0.9.3"
+ resolved "https://registry.yarnpkg.com/toml-eslint-parser/-/toml-eslint-parser-0.9.3.tgz#fc02498ba76e935f888c4b68b00e75b59789d272"
+ integrity sha512-moYoCvkNUAPCxSW9jmHmRElhm4tVJpHL8ItC/+uYD0EpPSFXbck7yREz9tNdJVTSpHVod8+HoipcpbQ0oE6gsw==
+ dependencies:
+ eslint-visitor-keys "^3.0.0"
+
+tough-cookie@~2.4.3:
+ version "2.4.3"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
+ integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==
+ dependencies:
+ psl "^1.1.24"
+ punycode "^1.4.1"
+
+tough-cookie@~2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
+ integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
+ dependencies:
+ psl "^1.1.28"
+ punycode "^2.1.1"
+
+tr46@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240"
+ integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==
+ dependencies:
+ punycode "^2.1.1"
+
+tr46@~0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
+ integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
+
+tree-kill@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
+ integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
+
+trim-newlines@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144"
+ integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==
+
+ts-api-utils@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1"
+ integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==
+
+tslib@^1.9.0:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
+ integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+
+tslib@^2.1.0, tslib@^2.3.1:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
+ integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
+
+tslib@^2.6.2:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
+ integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
+
+tunnel-agent@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+ integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==
+ dependencies:
+ safe-buffer "^5.0.1"
+
+tunnel@^0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c"
+ integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
+
+tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+ version "0.14.5"
+ resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
+ integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==
+
+type-check@^0.4.0, type-check@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
+ integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
+ dependencies:
+ prelude-ls "^1.2.1"
+
+type-detect@^4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
+ integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
+
+type-fest@^0.13.1:
+ version "0.13.1"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
+ integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==
+
+type-fest@^0.18.0:
+ version "0.18.1"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f"
+ integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==
+
+type-fest@^0.20.2:
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
+ integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
+
+type-fest@^0.21.3:
+ version "0.21.3"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
+ integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
+
+type-fest@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.4.1.tgz#8bdf77743385d8a4f13ba95f610f5ccd68c728f8"
+ integrity sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==
+
+type-fest@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
+ integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==
+
+type-fest@^0.8.1:
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
+ integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
+
+type-is@~1.6.18:
+ version "1.6.18"
+ resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
+ integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
+ dependencies:
+ media-typer "0.3.0"
+ mime-types "~2.1.24"
+
+typedarray-to-buffer@^3.1.5:
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
+ integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==
+ dependencies:
+ is-typedarray "^1.0.0"
+
+typedarray@^0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
+ integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
+
+typescript@^5.3.3:
+ version "5.3.3"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
+ integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
+
+ufo@^1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.3.2.tgz#c7d719d0628a1c80c006d2240e0d169f6e3c0496"
+ integrity sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==
+
+uglify-js@^3.1.4:
+ version "3.17.1"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.1.tgz#1258a2a488147a8266b3034499ce6959978ba7f4"
+ integrity sha512-+juFBsLLw7AqMaqJ0GFvlsGZwdQfI2ooKQB39PSBgMnMakcFosi9O8jCwE+2/2nMNcc0z63r9mwjoDG8zr+q0Q==
+
+uid-number@0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
+ integrity sha512-c461FXIljswCuscZn67xq9PpszkPT6RjheWFQTgCyabJrTUozElanb0YEqv2UGgk247YpcJkFBuSGNvBlpXM9w==
+
+umask@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d"
+ integrity sha512-lE/rxOhmiScJu9L6RTNVgB/zZbF+vGC0/p6D3xnkAePI2o0sMyFG966iR5Ki50OI/0mNi2yaRnxfLsPmEZF/JA==
+
+unbox-primitive@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"
+ integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==
+ dependencies:
+ call-bind "^1.0.2"
+ has-bigints "^1.0.2"
+ has-symbols "^1.0.3"
+ which-boxed-primitive "^1.0.2"
+
+undici-types@~5.26.4:
+ version "5.26.5"
+ resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
+ integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
+
+unicode-canonical-property-names-ecmascript@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc"
+ integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==
+
+unicode-match-property-ecmascript@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3"
+ integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==
+ dependencies:
+ unicode-canonical-property-names-ecmascript "^2.0.0"
+ unicode-property-aliases-ecmascript "^2.0.0"
+
+unicode-match-property-value-ecmascript@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714"
+ integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==
+
+unicode-property-aliases-ecmascript@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd"
+ integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==
+
+unicorn-magic@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/unicorn-magic/-/unicorn-magic-0.1.0.tgz#1bb9a51c823aaf9d73a8bfcd3d1a23dde94b0ce4"
+ integrity sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==
+
+unique-filename@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230"
+ integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==
+ dependencies:
+ unique-slug "^2.0.0"
+
+unique-slug@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c"
+ integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==
+ dependencies:
+ imurmurhash "^0.1.4"
+
+unist-util-stringify-position@^2.0.0:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da"
+ integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==
+ dependencies:
+ "@types/unist" "^2.0.2"
+
+universal-user-agent@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee"
+ integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==
+
+universalify@^0.1.0:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
+ integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+
+universalify@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
+ integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
+
+unpipe@1.0.0, unpipe@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+ integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
+
+upath@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b"
+ integrity sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==
+
+update-browserslist-db@^1.0.13:
+ version "1.0.13"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4"
+ integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==
+ dependencies:
+ escalade "^3.1.1"
+ picocolors "^1.0.0"
+
+update-browserslist-db@^1.0.9:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz#2924d3927367a38d5c555413a7ce138fc95fcb18"
+ integrity sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==
+ dependencies:
+ escalade "^3.1.1"
+ picocolors "^1.0.0"
+
+uri-js@^4.2.2:
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
+ integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
+ dependencies:
+ punycode "^2.1.0"
+
+urix@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
+ integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==
+
+url-parse-lax@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c"
+ integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==
+ dependencies:
+ prepend-http "^2.0.0"
+
+url@0.11.0, url@^0.11.0:
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
+ integrity sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==
+ dependencies:
+ punycode "1.3.2"
+ querystring "0.2.0"
+
+utf-8-validate@^5.0.9:
+ version "5.0.9"
+ resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.9.tgz#ba16a822fbeedff1a58918f2a6a6b36387493ea3"
+ integrity sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==
+ dependencies:
+ node-gyp-build "^4.3.0"
+
+util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+ integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
+
+util-promisify@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/util-promisify/-/util-promisify-2.1.0.tgz#3c2236476c4d32c5ff3c47002add7c13b9a82a53"
+ integrity sha512-K+5eQPYs14b3+E+hmE2J6gCZ4JmMl9DbYS6BeP2CHq6WMuNxErxf5B/n0fz85L8zUuoO6rIzNNmIQDu/j+1OcA==
+ dependencies:
+ object.getownpropertydescriptors "^2.0.3"
+
+utils-merge@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+ integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
+
+uuid@^3.3.2:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
+ integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
+
+uuid@^8.3.2:
+ version "8.3.2"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
+ integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
+
+v-tooltip@^3.0.0-alpha.20:
+ version "3.0.0-beta.20"
+ resolved "https://registry.yarnpkg.com/v-tooltip/-/v-tooltip-3.0.0-beta.20.tgz#d7636ce6684315b2bf949ea13f82fd829ca3d781"
+ integrity sha512-qoOy501P/CCpnWfAtxXiO1FDem8OPtxeubk9+LJU7g9dJTVu53RDimdUtKAtp9inTFVg/vqeRhezj2NfZyWOcg==
+ dependencies:
+ "@popperjs/core" "^2.11.0"
+ vue-resize "^1.0.0"
+
+validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
+ integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
+ dependencies:
+ spdx-correct "^3.0.0"
+ spdx-expression-parse "^3.0.0"
+
+validate-npm-package-name@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e"
+ integrity sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==
+ dependencies:
+ builtins "^1.0.3"
+
+vary@^1, vary@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+ integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
+
+verror@1.10.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
+ integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==
+ dependencies:
+ assert-plus "^1.0.0"
+ core-util-is "1.0.2"
+ extsprintf "^1.2.0"
+
+vite@^2.9.7:
+ version "2.9.15"
+ resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.15.tgz#2858dd5b2be26aa394a283e62324281892546f0b"
+ integrity sha512-fzMt2jK4vQ3yK56te3Kqpkaeq9DkcZfBbzHwYpobasvgYmP2SoAr6Aic05CsB4CzCZbsDv4sujX3pkEGhLabVQ==
+ dependencies:
+ esbuild "^0.14.27"
+ postcss "^8.4.13"
+ resolve "^1.22.0"
+ rollup ">=2.59.0 <2.78.0"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+vitepress@^0.22.3:
+ version "0.22.4"
+ resolved "https://registry.yarnpkg.com/vitepress/-/vitepress-0.22.4.tgz#d4d778fb06decfc2c31c105f6a7a136843cdfb08"
+ integrity sha512-oZUnLO/SpYdThaBKefDeOiVlr0Rie4Ppx3FzMnMyLtJnI5GlBMNjqYqMy/4+umm/iC+ZDJfI+IlDKxv5fZnYzA==
+ dependencies:
+ "@docsearch/css" "^3.0.0"
+ "@docsearch/js" "^3.0.0"
+ "@vitejs/plugin-vue" "^2.3.2"
+ prismjs "^1.25.0"
+ vite "^2.9.7"
+ vue "^3.2.33"
+
+vue-demi@>=0.14.6:
+ version "0.14.7"
+ resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.7.tgz#8317536b3ef74c5b09f268f7782e70194567d8f2"
+ integrity sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==
+
+vue-eslint-parser@^9.4.2:
+ version "9.4.2"
+ resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz#02ffcce82042b082292f2d1672514615f0d95b6d"
+ integrity sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==
+ dependencies:
+ debug "^4.3.4"
+ eslint-scope "^7.1.1"
+ eslint-visitor-keys "^3.3.0"
+ espree "^9.3.1"
+ esquery "^1.4.0"
+ lodash "^4.17.21"
+ semver "^7.3.6"
+
+vue-hot-reload-api@^2.3.0:
+ version "2.3.4"
+ resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"
+ integrity sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==
+
+vue-loader@^15.7.1:
+ version "15.10.0"
+ resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.10.0.tgz#2a12695c421a2a2cc2138f05a949d04ed086e38b"
+ integrity sha512-VU6tuO8eKajrFeBzMssFUP9SvakEeeSi1BxdTH5o3+1yUyrldp8IERkSdXlMI2t4kxF2sqYUDsQY+WJBxzBmZg==
+ dependencies:
+ "@vue/component-compiler-utils" "^3.1.0"
+ hash-sum "^1.0.2"
+ loader-utils "^1.1.0"
+ vue-hot-reload-api "^2.3.0"
+ vue-style-loader "^4.1.0"
+
+vue-loader@^17.2.2:
+ version "17.2.2"
+ resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-17.2.2.tgz#96148eb70c1365cc8c5bab4274923596811c79df"
+ integrity sha512-aqNvKJvnz2A/6VWeJZodAo8XLoAlVwBv+2Z6dama+LHsAF+P/xijQ+OfWrxIs0wcGSJduvdzvTuATzXbNKkpiw==
+ dependencies:
+ chalk "^4.1.0"
+ hash-sum "^2.0.0"
+ watchpack "^2.4.0"
+
+vue-observe-visibility@^2.0.0-alpha.1:
+ version "2.0.0-alpha.1"
+ resolved "https://registry.yarnpkg.com/vue-observe-visibility/-/vue-observe-visibility-2.0.0-alpha.1.tgz#1e4eda7b12562161d58984b7e0dea676d83bdb13"
+ integrity sha512-flFbp/gs9pZniXR6fans8smv1kDScJ8RS7rEpMjhVabiKeq7Qz3D9+eGsypncjfIyyU84saU88XZ0zjbD6Gq/g==
+
+vue-resize@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/vue-resize/-/vue-resize-1.0.1.tgz#c120bed4e09938771d622614f57dbcf58a5147ee"
+ integrity sha512-z5M7lJs0QluJnaoMFTIeGx6dIkYxOwHThlZDeQnWZBizKblb99GSejPnK37ZbNE/rVwDcYcHY+Io+AxdpY952w==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+
+vue-resize@^2.0.0-alpha.1:
+ version "2.0.0-alpha.1"
+ resolved "https://registry.yarnpkg.com/vue-resize/-/vue-resize-2.0.0-alpha.1.tgz#43eeb79e74febe932b9b20c5c57e0ebc14e2df3a"
+ integrity sha512-7+iqOueLU7uc9NrMfrzbG8hwMqchfVfSzpVlCMeJQe4pyibqyoifDNbKTZvwxZKDvGkB+PdFeKvnGZMoEb8esg==
+
+vue-router@^3.6.5:
+ version "3.6.5"
+ resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.6.5.tgz#95847d52b9a7e3f1361cb605c8e6441f202afad8"
+ integrity sha512-VYXZQLtjuvKxxcshuRAwjHnciqZVoXAjTjcqBTz4rKc8qih9g9pI3hbDjmqXaHdgL3v8pV6P8Z335XvHzESxLQ==
+
+vue-router@^4.2.5:
+ version "4.2.5"
+ resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.2.5.tgz#b9e3e08f1bd9ea363fdd173032620bc50cf0e98a"
+ integrity sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==
+ dependencies:
+ "@vue/devtools-api" "^6.5.0"
+
+vue-safe-teleport@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/vue-safe-teleport/-/vue-safe-teleport-0.1.2.tgz#0d6f464acef0687a098a1ffcb2ef497edd39188e"
+ integrity sha512-L6S/ALd5I7hXWi2T5HETHKCW9bku0hNx4ocIWRsk46h1IfNvjXxtLE9ECV4SDJFkcTAn3pMf9yxftBYLoZ3USQ==
+
+vue-style-loader@^4.1.0:
+ version "4.1.3"
+ resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.3.tgz#6d55863a51fa757ab24e89d9371465072aa7bc35"
+ integrity sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==
+ dependencies:
+ hash-sum "^1.0.2"
+ loader-utils "^1.0.2"
+
+vue-template-es2015-compiler@^1.9.0:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
+ integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
+
+vue-virtual-scroller@^2.0.0-alpha.1:
+ version "2.0.0-beta.8"
+ resolved "https://registry.yarnpkg.com/vue-virtual-scroller/-/vue-virtual-scroller-2.0.0-beta.8.tgz#eeceda57e4faa5ba1763994c873923e2a956898b"
+ integrity sha512-b8/f5NQ5nIEBRTNi6GcPItE4s7kxNHw2AIHLtDp+2QvqdTjVN0FgONwX9cr53jWRgnu+HRLPaWDOR2JPI5MTfQ==
+ dependencies:
+ mitt "^2.1.0"
+ vue-observe-visibility "^2.0.0-alpha.1"
+ vue-resize "^2.0.0-alpha.1"
+
+vue@^2.7.10:
+ version "2.7.10"
+ resolved "https://registry.yarnpkg.com/vue/-/vue-2.7.10.tgz#ae516cc6c88e1c424754468844218fdd5e280f40"
+ integrity sha512-HmFC70qarSHPXcKtW8U8fgIkF6JGvjEmDiVInTkKZP0gIlEPhlVlcJJLkdGIDiNkIeA2zJPQTWJUI4iWe+AVfg==
+ dependencies:
+ "@vue/compiler-sfc" "2.7.10"
+ csstype "^3.1.0"
+
+vue@^3.2.0, vue@^3.2.33:
+ version "3.2.39"
+ resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.39.tgz#de071c56c4c32c41cbd54e55f11404295c0dd62d"
+ integrity sha512-tRkguhRTw9NmIPXhzk21YFBqXHT2t+6C6wPOgQ50fcFVWnPdetmRqbmySRHznrYjX2E47u0cGlKGcxKZJ38R/g==
+ dependencies:
+ "@vue/compiler-dom" "3.2.39"
+ "@vue/compiler-sfc" "3.2.39"
+ "@vue/runtime-dom" "3.2.39"
+ "@vue/server-renderer" "3.2.39"
+ "@vue/shared" "3.2.39"
+
+vue@^3.3.4:
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/vue/-/vue-3.3.4.tgz#8ed945d3873667df1d0fcf3b2463ada028f88bd6"
+ integrity sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==
+ dependencies:
+ "@vue/compiler-dom" "3.3.4"
+ "@vue/compiler-sfc" "3.3.4"
+ "@vue/runtime-dom" "3.3.4"
+ "@vue/server-renderer" "3.3.4"
+ "@vue/shared" "3.3.4"
+
+vuex@^3.6.2:
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.6.2.tgz#236bc086a870c3ae79946f107f16de59d5895e71"
+ integrity sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==
+
+vuex@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/vuex/-/vuex-4.0.2.tgz#f896dbd5bf2a0e963f00c67e9b610de749ccacc9"
+ integrity sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==
+ dependencies:
+ "@vue/devtools-api" "^6.0.0-beta.11"
+
+wait-on@6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-6.0.0.tgz#7e9bf8e3d7fe2daecbb7a570ac8ca41e9311c7e7"
+ integrity sha512-tnUJr9p5r+bEYXPUdRseolmz5XqJTTj98JgOsfBn7Oz2dxfE2g3zw1jE+Mo8lopM3j3et/Mq1yW7kKX6qw7RVw==
+ dependencies:
+ axios "^0.21.1"
+ joi "^17.4.0"
+ lodash "^4.17.21"
+ minimist "^1.2.5"
+ rxjs "^7.1.0"
+
+watchpack@^2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
+ integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
+ dependencies:
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.1.2"
+
+wbuf@^1.1.0, wbuf@^1.7.3:
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df"
+ integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==
+ dependencies:
+ minimalistic-assert "^1.0.0"
+
+wcwidth@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
+ integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==
+ dependencies:
+ defaults "^1.0.3"
+
+webidl-conversions@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
+ integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
+
+webidl-conversions@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
+ integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
+
+webpack-cli@^4.6.0:
+ version "4.10.0"
+ resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31"
+ integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==
+ dependencies:
+ "@discoveryjs/json-ext" "^0.5.0"
+ "@webpack-cli/configtest" "^1.2.0"
+ "@webpack-cli/info" "^1.5.0"
+ "@webpack-cli/serve" "^1.7.0"
+ colorette "^2.0.14"
+ commander "^7.0.0"
+ cross-spawn "^7.0.3"
+ fastest-levenshtein "^1.0.12"
+ import-local "^3.0.2"
+ interpret "^2.2.0"
+ rechoir "^0.7.0"
+ webpack-merge "^5.7.3"
+
+webpack-cli@^5.1.4:
+ version "5.1.4"
+ resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b"
+ integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==
+ dependencies:
+ "@discoveryjs/json-ext" "^0.5.0"
+ "@webpack-cli/configtest" "^2.1.1"
+ "@webpack-cli/info" "^2.0.2"
+ "@webpack-cli/serve" "^2.0.5"
+ colorette "^2.0.14"
+ commander "^10.0.1"
+ cross-spawn "^7.0.3"
+ envinfo "^7.7.3"
+ fastest-levenshtein "^1.0.12"
+ import-local "^3.0.2"
+ interpret "^3.1.1"
+ rechoir "^0.8.0"
+ webpack-merge "^5.7.3"
+
+webpack-dev-middleware@^5.3.1:
+ version "5.3.3"
+ resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f"
+ integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==
+ dependencies:
+ colorette "^2.0.10"
+ memfs "^3.4.3"
+ mime-types "^2.1.31"
+ range-parser "^1.2.1"
+ schema-utils "^4.0.0"
+
+webpack-dev-server@^4.15.1:
+ version "4.15.1"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz#8944b29c12760b3a45bdaa70799b17cb91b03df7"
+ integrity sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==
+ dependencies:
+ "@types/bonjour" "^3.5.9"
+ "@types/connect-history-api-fallback" "^1.3.5"
+ "@types/express" "^4.17.13"
+ "@types/serve-index" "^1.9.1"
+ "@types/serve-static" "^1.13.10"
+ "@types/sockjs" "^0.3.33"
+ "@types/ws" "^8.5.5"
+ ansi-html-community "^0.0.8"
+ bonjour-service "^1.0.11"
+ chokidar "^3.5.3"
+ colorette "^2.0.10"
+ compression "^1.7.4"
+ connect-history-api-fallback "^2.0.0"
+ default-gateway "^6.0.3"
+ express "^4.17.3"
+ graceful-fs "^4.2.6"
+ html-entities "^2.3.2"
+ http-proxy-middleware "^2.0.3"
+ ipaddr.js "^2.0.1"
+ launch-editor "^2.6.0"
+ open "^8.0.9"
+ p-retry "^4.5.0"
+ rimraf "^3.0.2"
+ schema-utils "^4.0.0"
+ selfsigned "^2.1.1"
+ serve-index "^1.9.1"
+ sockjs "^0.3.24"
+ spdy "^4.0.2"
+ webpack-dev-middleware "^5.3.1"
+ ws "^8.13.0"
+
+webpack-merge@^5.10.0:
+ version "5.10.0"
+ resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177"
+ integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==
+ dependencies:
+ clone-deep "^4.0.1"
+ flat "^5.0.2"
+ wildcard "^2.0.0"
+
+webpack-merge@^5.7.3:
+ version "5.8.0"
+ resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61"
+ integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==
+ dependencies:
+ clone-deep "^4.0.1"
+ wildcard "^2.0.0"
+
+webpack-sources@^1.1.0:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
+ integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==
+ dependencies:
+ source-list-map "^2.0.0"
+ source-map "~0.6.1"
+
+webpack-sources@^2.2.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd"
+ integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==
+ dependencies:
+ source-list-map "^2.0.1"
+ source-map "^0.6.1"
+
+webpack-sources@^3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
+ integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
+
+webpack@^5.35.1, webpack@^5.90.1:
+ version "5.90.1"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.90.1.tgz#62ab0c097d7cbe83d32523dbfbb645cdb7c3c01c"
+ integrity sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog==
+ dependencies:
+ "@types/eslint-scope" "^3.7.3"
+ "@types/estree" "^1.0.5"
+ "@webassemblyjs/ast" "^1.11.5"
+ "@webassemblyjs/wasm-edit" "^1.11.5"
+ "@webassemblyjs/wasm-parser" "^1.11.5"
+ acorn "^8.7.1"
+ acorn-import-assertions "^1.9.0"
+ browserslist "^4.21.10"
+ chrome-trace-event "^1.0.2"
+ enhanced-resolve "^5.15.0"
+ es-module-lexer "^1.2.1"
+ eslint-scope "5.1.1"
+ events "^3.2.0"
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.2.9"
+ json-parse-even-better-errors "^2.3.1"
+ loader-runner "^4.2.0"
+ mime-types "^2.1.27"
+ neo-async "^2.6.2"
+ schema-utils "^3.2.0"
+ tapable "^2.1.1"
+ terser-webpack-plugin "^5.3.10"
+ watchpack "^2.4.0"
+ webpack-sources "^3.2.3"
+
+websocket-driver@>=0.5.1, websocket-driver@^0.7.4:
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"
+ integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==
+ dependencies:
+ http-parser-js ">=0.5.1"
+ safe-buffer ">=5.1.0"
+ websocket-extensions ">=0.1.1"
+
+websocket-extensions@>=0.1.1:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
+ integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
+
+whatwg-url@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
+ integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
+ dependencies:
+ tr46 "~0.0.3"
+ webidl-conversions "^3.0.0"
+
+whatwg-url@^8.4.0:
+ version "8.7.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77"
+ integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==
+ dependencies:
+ lodash "^4.7.0"
+ tr46 "^2.1.0"
+ webidl-conversions "^6.1.0"
+
+when@~3.6.x:
+ version "3.6.4"
+ resolved "https://registry.yarnpkg.com/when/-/when-3.6.4.tgz#473b517ec159e2b85005497a13983f095412e34e"
+ integrity sha512-d1VUP9F96w664lKINMGeElWdhhb5sC+thXM+ydZGU3ZnaE09Wv6FaS+mpM9570kcDs/xMfcXJBTLsMdHEFYY9Q==
+
+which-boxed-primitive@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
+ integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==
+ 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"
+
+which-module@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
+ integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==
+
+which@^1.2.9, which@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
+ integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
+ dependencies:
+ isexe "^2.0.0"
+
+which@^2.0.1, which@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+ dependencies:
+ isexe "^2.0.0"
+
+wide-align@^1.1.0:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
+ integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==
+ dependencies:
+ string-width "^1.0.2 || 2 || 3 || 4"
+
+wildcard@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec"
+ integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==
+
+wordwrap@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+ integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==
+
+wrap-ansi@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09"
+ integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==
+ dependencies:
+ ansi-styles "^3.2.0"
+ string-width "^3.0.0"
+ strip-ansi "^5.0.0"
+
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+
+write-file-atomic@^2.4.2:
+ version "2.4.3"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
+ integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==
+ dependencies:
+ graceful-fs "^4.1.11"
+ imurmurhash "^0.1.4"
+ signal-exit "^3.0.2"
+
+write-file-atomic@^3.0.0, write-file-atomic@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"
+ integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==
+ dependencies:
+ imurmurhash "^0.1.4"
+ is-typedarray "^1.0.0"
+ signal-exit "^3.0.2"
+ typedarray-to-buffer "^3.1.5"
+
+write-json-file@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-3.2.0.tgz#65bbdc9ecd8a1458e15952770ccbadfcff5fe62a"
+ integrity sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==
+ dependencies:
+ detect-indent "^5.0.0"
+ graceful-fs "^4.1.15"
+ make-dir "^2.1.0"
+ pify "^4.0.1"
+ sort-keys "^2.0.0"
+ write-file-atomic "^2.4.2"
+
+write-json-file@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-4.3.0.tgz#908493d6fd23225344af324016e4ca8f702dd12d"
+ integrity sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==
+ dependencies:
+ detect-indent "^6.0.0"
+ graceful-fs "^4.1.15"
+ is-plain-obj "^2.0.0"
+ make-dir "^3.0.0"
+ sort-keys "^4.0.0"
+ write-file-atomic "^3.0.0"
+
+write-pkg@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/write-pkg/-/write-pkg-4.0.0.tgz#675cc04ef6c11faacbbc7771b24c0abbf2a20039"
+ integrity sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==
+ dependencies:
+ sort-keys "^2.0.0"
+ type-fest "^0.4.1"
+ write-json-file "^3.2.0"
+
+ws@^8.13.0:
+ version "8.16.0"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4"
+ integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==
+
+ws@~8.2.3:
+ version "8.2.3"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba"
+ integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==
+
+xml-name-validator@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835"
+ integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==
+
+xmlhttprequest-ssl@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67"
+ integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==
+
+xtend@^4.0.2, xtend@~4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
+ integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
+
+y18n@^4.0.0:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
+ integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
+
+y18n@^5.0.5:
+ version "5.0.8"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
+ integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
+
+yallist@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
+ integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==
+
+yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
+ integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
+
+yallist@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
+yaml-eslint-parser@^1.2.1:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/yaml-eslint-parser/-/yaml-eslint-parser-1.2.2.tgz#1a9673ebe254328cfc2fa99f297f6d8c9364ccd8"
+ integrity sha512-pEwzfsKbTrB8G3xc/sN7aw1v6A6c/pKxLAkjclnAyo5g5qOh6eL9WGu0o3cSDQZKrTNk4KL4lQSwZW+nBkANEg==
+ dependencies:
+ eslint-visitor-keys "^3.0.0"
+ lodash "^4.17.21"
+ yaml "^2.0.0"
+
+yaml-eslint-parser@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/yaml-eslint-parser/-/yaml-eslint-parser-1.2.3.tgz#3a8ae839fc8df376ef8497add7f40942b493389c"
+ integrity sha512-4wZWvE398hCP7O8n3nXKu/vdq1HcH01ixYlCREaJL5NUMwQ0g3MaGFUBNSlmBtKmhbtVG/Cm6lyYmSVTEVil8A==
+ dependencies:
+ eslint-visitor-keys "^3.0.0"
+ lodash "^4.17.21"
+ yaml "^2.0.0"
+
+yaml@^1.10.0, yaml@^1.10.2:
+ version "1.10.2"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
+ integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
+
+yaml@^2.0.0:
+ version "2.3.4"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2"
+ integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==
+
+yargs-parser@20.2.4:
+ version "20.2.4"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"
+ integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==
+
+yargs-parser@^13.1.2:
+ version "13.1.2"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
+ integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==
+ dependencies:
+ camelcase "^5.0.0"
+ decamelize "^1.2.0"
+
+yargs-parser@^20.2.2, yargs-parser@^20.2.3:
+ version "20.2.9"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
+ integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
+
+yargs-parser@^21.1.1:
+ version "21.1.1"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
+ integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
+
+yargs@^13.3.0:
+ version "13.3.2"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
+ integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==
+ dependencies:
+ cliui "^5.0.0"
+ find-up "^3.0.0"
+ get-caller-file "^2.0.1"
+ require-directory "^2.1.1"
+ require-main-filename "^2.0.0"
+ set-blocking "^2.0.0"
+ string-width "^3.0.0"
+ which-module "^2.0.0"
+ y18n "^4.0.0"
+ yargs-parser "^13.1.2"
+
+yargs@^16.2.0:
+ version "16.2.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
+ integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
+ 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"
+
+yargs@^17.7.2:
+ version "17.7.2"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
+ integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
+ 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"
+
+yauzl@2.10.0, yauzl@^2.10.0:
+ version "2.10.0"
+ resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
+ integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==
+ dependencies:
+ buffer-crc32 "~0.2.3"
+ fd-slicer "~1.1.0"
+
+yauzl@2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005"
+ integrity sha512-TXNR2Feu/p/8k5YRy4z45wCUhoncIrZywmRd+xW0IvB3lWTAM7F6wVbeJvRjO0dplQ8oqmJEj/TpJuULBV/hbw==
+ dependencies:
+ fd-slicer "~1.0.1"
+
+yocto-queue@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
+ integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
+
+yocto-queue@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251"
+ integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==
+
+zip-stream@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.1.0.tgz#51dd326571544e36aa3f756430b313576dc8fc79"
+ integrity sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==
+ dependencies:
+ archiver-utils "^2.1.0"
+ compress-commons "^4.1.0"
+ readable-stream "^3.6.0"
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..ae4279fba9cb74e22f73da68f6cbdb6e4f29b528
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,117 @@
+const autoprefixer = require('autoprefixer')
+const postcss = require('postcss')
+const webpack = require('webpack')
+const path = require('path')
+const pkg = require('./package.json')
+const classPrefix = require('postcss-class-prefix')
+const TerserPlugin = require('terser-webpack-plugin')
+
+const banner = pkg.name + ' v' + pkg.version + ' ' + pkg.homepage
+
+module.exports = (env, argv) => {
+ const config = {
+ devtool: 'source-map',
+ entry: './src/index.js',
+ devServer: {
+ static: {
+ directory: path.join(__dirname, './'),
+ },
+ port: 8080,
+ },
+ watchOptions: {
+ aggregateTimeout: 300,
+ poll: 1000,
+ ignored: /node_modules/,
+ },
+ resolve: {
+ extensions: ['.js'],
+ fallback: {
+ path: require.resolve('path-browserify'),
+ },
+ alias: {
+ '@front': '@vue-devtools/app-frontend/src',
+ '@back': '@vue-devtools/app-backend-core/lib',
+ '@utils': '@vue-devtools/shared-utils/lib',
+ }
+ },
+ output: {
+ path: __dirname,
+ filename: 'eruda-vue.js',
+ publicPath: '/assets/',
+ library: ['erudaVue'],
+ libraryTarget: 'umd',
+ },
+ module: {
+ rules: [
+ {
+ test: /\.js$/,
+ exclude: /node_modules/,
+ use: {
+ loader: 'babel-loader',
+ options: {
+ sourceType: 'unambiguous',
+ presets: ['@babel/preset-env'],
+ plugins: ['@babel/plugin-transform-runtime'],
+ },
+ },
+ },
+ {
+ test: /\.scss$/,
+ use: [
+ 'css-loader',
+ {
+ loader: 'postcss-loader',
+ options: {
+ postcssOptions: {
+ plugins: [
+ postcss.plugin('postcss-namespace', function () {
+ // Add '.dev-tools .tools ' to every selector.
+ return function (root) {
+ root.walkRules(function (rule) {
+ if (!rule.selectors) return rule
+
+ rule.selectors = rule.selectors.map(function (
+ selector
+ ) {
+ return '.dev-tools .tools ' + selector
+ })
+ })
+ }
+ }),
+ classPrefix('eruda-'),
+ autoprefixer,
+ ],
+ },
+ },
+ },
+ 'sass-loader',
+ ],
+ },
+ ],
+ },
+ plugins: [
+ new webpack.optimize.LimitChunkCountPlugin({
+ maxChunks: 1,
+ }),
+ new webpack.BannerPlugin(banner)
+ ],
+ }
+
+ if (argv.mode === 'production') {
+ config.optimization = {
+ minimize: true,
+ minimizer: [
+ new TerserPlugin({
+ terserOptions: {
+ format: {
+ comments: false,
+ },
+ },
+ extractComments: false,
+ }),
+ ],
+ }
+ }
+
+ return config
+}