diff --git a/app/web/.env b/app/web/.env index 9bf7c2b8cb..43730d0230 100644 --- a/app/web/.env +++ b/app/web/.env @@ -7,6 +7,11 @@ VITE_API_PROXY_PATH=/api VITE_AUTH_API_URL=https://auth-api.systeminit.com VITE_AUTH_PORTAL_URL=https://auth.systeminit.com +VITE_AUTH0_DOMAIN=systeminit.auth0.com + +# Add to env.local for Cypress E2E Testing +#VITE_AUTH0_USERNAME +#VITE_AUTH0_PASSWORD # TODO: point this at public/deployed module index api VITE_MODULE_INDEX_API_URL=https://module-index.systeminit.com diff --git a/app/web/cypress.config.ts b/app/web/cypress.config.ts new file mode 100644 index 0000000000..7442d7853c --- /dev/null +++ b/app/web/cypress.config.ts @@ -0,0 +1,19 @@ +import path from 'path' +import { defineConfig } from 'cypress' +import vitePreprocessor from 'cypress-vite' + + + +export default defineConfig({ + e2e: { + setupNodeEvents(on, config) { + on('file:preprocessor', vitePreprocessor(path.resolve('./vite.config.ts'), + )) + }, + baseUrl: 'http://localhost:8080', + chromeWebSecurity: false, + viewportHeight: 1000, + viewportWidth: 1500, + } +}) + diff --git a/app/web/cypress.d.ts b/app/web/cypress.d.ts new file mode 100644 index 0000000000..1cfa5f8c2e --- /dev/null +++ b/app/web/cypress.d.ts @@ -0,0 +1,12 @@ +import { mount } from 'cypress/vue'; + +type MountParams = Parameters; +type OptionsParam = MountParams[1]; + +declare global { + namespace Cypress { + interface Chainable { + mount: typeof mount; + } + } +} \ No newline at end of file diff --git a/app/web/cypress.json b/app/web/cypress.json deleted file mode 100644 index d1ab2fc04f..0000000000 --- a/app/web/cypress.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "baseUrl": "http://localhost:8080" -} diff --git a/app/web/cypress/e2e/1-signup/signup.cy.ts b/app/web/cypress/e2e/1-signup/signup.cy.ts new file mode 100644 index 0000000000..7e6589d75d --- /dev/null +++ b/app/web/cypress/e2e/1-signup/signup.cy.ts @@ -0,0 +1,17 @@ +//TODO: Bring this back to life + +// describe("Signup", () => { +// beforeEach(() => { +// cy.visit("authenticate/signup"); +// }); + +// it("lets the user create a new account", () => { +// cy.getBySel("workspaceName").type("bobo"); +// cy.getBySel("userName").type("bobo clown"); +// cy.getBySel("userEmail").type("bobo@systeminit.com"); +// cy.getBySel("userPassword").type("Bobo42!ggz"); +// cy.getBySel("signupSecret").type("cool-steam"); +// cy.getBySel("signUp").click(); +// cy.url().should("be.match", /\/authenticate\/login$/); +// }); +// }); diff --git a/app/web/cypress/e2e/2-login/login.cy.ts b/app/web/cypress/e2e/2-login/login.cy.ts new file mode 100644 index 0000000000..25cec0f136 --- /dev/null +++ b/app/web/cypress/e2e/2-login/login.cy.ts @@ -0,0 +1,13 @@ +describe("Login", () => { + beforeEach(() => { + cy.visit("/"); + }); + + it("lets the user log in", () => { + cy.loginToAuth0(import.meta.env.VITE_AUTH0_USERNAME, import.meta.env.VITE_AUTH0_PASSWORD); + cy.visit("/"); + // check that you're on head + cy.url().should("contain", "head"); + }); + +}); diff --git a/app/web/cypress/e2e/2-login/logout.cy.ts b/app/web/cypress/e2e/2-login/logout.cy.ts new file mode 100644 index 0000000000..041213b7dc --- /dev/null +++ b/app/web/cypress/e2e/2-login/logout.cy.ts @@ -0,0 +1,15 @@ +describe("Logout", () => { + beforeEach(() => { + cy.visit("/"); + cy.loginToAuth0(import.meta.env.VITE_AUTH0_USERNAME, import.meta.env.VITE_AUTH0_PASSWORD); + }); + + it("lets the user log out", () => { + cy.visit("/"); + cy.contains('Create change set', { timeout: 10000 }).should('be.visible').click(); + cy.get('[aria-label="Profile"]').should('exist').click(); + cy.get('#dropdown-menu-item-1').should('exist').should('be.visible').click({ force: true }); + cy.url().should("contain", import.meta.env.VITE_AUTH_PORTAL_URL + '/logout'); + + }); +}); diff --git a/app/web/cypress/e2e/3-create-components/create-component.cy.ts b/app/web/cypress/e2e/3-create-components/create-component.cy.ts new file mode 100644 index 0000000000..12241a7991 --- /dev/null +++ b/app/web/cypress/e2e/3-create-components/create-component.cy.ts @@ -0,0 +1,27 @@ +// @ts-check +/// + +describe('Create Components', () => { + beforeEach(function () { + cy.loginToAuth0(import.meta.env.VITE_AUTH0_USERNAME, import.meta.env.VITE_AUTH0_PASSWORD); + }); + + it('should pick up an AWS Credential and move it onto the diagram', () => { + cy.visit('/') + cy.contains('Create change set', { timeout: 10000 }).should('be.visible').click(); + + // Find the AWS Credential + cy.get('[data-cy="asset_card', { timeout: 10000 }).contains('AWS Credential').should('be.visible').as('awsCred') + + // Find the canvas to get a location to drag to + cy.get('canvas').first().as('konvaStage'); + + // drag to the canvas + cy.dragTo('@awsCred', '@konvaStage'); + + //check to make sure a component has been added to the outliner + cy.get('[class="component-outline-node"]', { timeout: 10000 }).contains('AWS Credential').should('be.visible'); + + }) +}) + diff --git a/app/web/cypress/global.d.ts b/app/web/cypress/global.d.ts index 3453a16956..d08e0b867e 100644 --- a/app/web/cypress/global.d.ts +++ b/app/web/cypress/global.d.ts @@ -2,7 +2,7 @@ declare namespace Cypress { - interface CustomWindow extends Window {} + interface CustomWindow extends Window { } interface Chainable { /** @@ -11,15 +11,14 @@ declare namespace Cypress { */ window(options?: Partial): Chainable; + getBySel(dataTestAttribute: string, args?: any): Chainable>; + getBySelLike(dataTestPrefixAttribute: string, args?: any): Chainable>; + /** - * Custom command to select DOM element by data-cy attribute. - * @example cy.dataCy('greeting') + * Logs in via Auth0 login page */ - getBySel(value: string): Chainable; - - getBySelLike(value: string): Chainable; + loginToAuth0(username: string, password: string): Chainable; - signup(): Chainable>; - signupAndLogin(): Chainable>; + dragTo(sourceElement: string, targetElement: string): void; } } diff --git a/app/web/cypress/integration/1-signup/signup.spec.ts b/app/web/cypress/integration/1-signup/signup.spec.ts deleted file mode 100644 index 954e8b1549..0000000000 --- a/app/web/cypress/integration/1-signup/signup.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -/// - -describe("Signup", () => { - beforeEach(() => { - cy.visit("authenticate/signup"); - }); - - it("lets the user create a new account", () => { - cy.getBySel("workspaceName").type("bobo"); - cy.getBySel("userName").type("bobo clown"); - cy.getBySel("userEmail").type("bobo@systeminit.com"); - cy.getBySel("userPassword").type("Bobo42!ggz"); - cy.getBySel("signupSecret").type("cool-steam"); - cy.getBySel("signUp").click(); - cy.url().should("be.match", /\/authenticate\/login$/); - }); -}); diff --git a/app/web/cypress/integration/2-login/login.spec.ts b/app/web/cypress/integration/2-login/login.spec.ts deleted file mode 100644 index 31004a9ab6..0000000000 --- a/app/web/cypress/integration/2-login/login.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { TestCtx } from "../../support/commands"; - -describe("Login", () => { - beforeEach(() => { - cy.visit("/"); - cy.signup(); - }); - - it("lets the user log in", () => { - cy.visit("authenticate/login"); - cy.get("@nw").then((testCtx: any) => { - cy.getBySel("workspaceName").type(testCtx.workspaceName); - cy.getBySel("userEmail").type(testCtx.userEmail); - cy.getBySel("userPassword").type("snakes"); - cy.getBySel("login") - .click() - .should(() => { - expect(localStorage.getItem("si-sdf-token")).to.not.be.null; - }); - cy.url().should("be.match", /\/$/); - }); - }); -}); diff --git a/app/web/cypress/integration/2-login/logout.spec.ts b/app/web/cypress/integration/2-login/logout.spec.ts deleted file mode 100644 index e58f26be55..0000000000 --- a/app/web/cypress/integration/2-login/logout.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -describe("Logout", () => { - beforeEach(() => { - cy.visit("/"); - cy.signupAndLogin(); - }); - - it("lets the user log out", () => { - cy.visit("/"); - cy.get("@nw").then((testCtx: any) => { - cy.getBySel("logout") - .click() - .should(() => { - expect(localStorage.getItem("si-sdf-token")).to.be.null; - }); - cy.url().should("be.match", /\/authenticate\/login$/); - }); - }); -}); diff --git a/app/web/cypress/plugins/index.ts b/app/web/cypress/plugins/index.ts deleted file mode 100644 index 3220a6b5dc..0000000000 --- a/app/web/cypress/plugins/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/// -// *********************************************************** -// 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) - -/** - * @type {Cypress.PluginConfig} - */ -export default (on, config) => {}; diff --git a/app/web/cypress/support/auth-provider-commands/auth0.ts b/app/web/cypress/support/auth-provider-commands/auth0.ts new file mode 100644 index 0000000000..0814aea04b --- /dev/null +++ b/app/web/cypress/support/auth-provider-commands/auth0.ts @@ -0,0 +1,55 @@ +// @ts-check +/// + +// Note: this function leaves you on a blank page, so you must call cy.visit() +// afterwards, before continuing with your test. +Cypress.Commands.add("loginToAuth0", (username: string, password: string) => { + const log = Cypress.log({ + displayName: "AUTH0 LOGIN", + message: [`🔐 Authenticating | ${username}`], + // @ts-ignore + autoEnd: false, + }); + log.snapshot("before"); + + const args = { username, password }; + cy.session( + `auth0-${username}`, + () => { + // App landing page redirects to Auth0. + cy.visit("/"); + cy.url().should("contain", import.meta.env.VITE_AUTH0_DOMAIN); + // Login on Auth0. + cy.origin(import.meta.env.VITE_AUTH0_DOMAIN, { args }, ({ username, password }) => { + cy.get("input#username").type(username); + cy.contains('Continue').click(); + cy.get("input#password").type(password).type('{enter}'); + + }); + + // Ensure Auth0 has redirected us back to the auth portal. + cy.url().should("contain", import.meta.env.VITE_AUTH_PORTAL_URL); + + // click the link to go back to the local app + cy.origin(import.meta.env.VITE_AUTH_PORTAL_URL, () => { + + //todo: use a more reliable way to get the link to navigate back to + cy.contains('div', 'Role: Owner') + .parent('div').parent('a') + .should('exist').invoke('attr', 'href') + .then(($href) => { + cy.visit($href); + }); + }); + }, + { + validate: () => { + // Validate presence of access token in localStorage. + cy.window().its("localStorage").invoke("getItem", "si-auth").should("exist"); + }, + } + ); + + log.snapshot("after"); + log.end(); +}); \ No newline at end of file diff --git a/app/web/cypress/support/commands.ts b/app/web/cypress/support/commands.ts index 22dfb56d03..1f5a24ff14 100644 --- a/app/web/cypress/support/commands.ts +++ b/app/web/cypress/support/commands.ts @@ -1,4 +1,5 @@ -/// +// @ts-check +/// // *********************************************** // This example commands.js shows you how to @@ -26,100 +27,38 @@ // -- This will overwrite an existing command -- // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) -import { Workspace } from "../../src/api/sdf/dal/workspace"; -import { User } from "../../src/api/sdf/dal/user"; -import { PublicKey } from "../../src/api/sdf/dal/key_pair"; -import Bottle from "bottlejs"; -import { user$ } from "../../src/observable/user"; -import { SDF } from "../../src/api/sdf"; -import { SessionService } from "../../src/service/session"; -import faker from "faker"; -import { CreateAccountRequest } from "../../src/service/signup/create_account"; -import { firstValueFrom } from "rxjs"; +// Import commands for auth0 auth providers +import "./auth-provider-commands/auth0"; Cypress.Commands.add("getBySel", (selector, ...args) => { - return cy.get(`[data-test=${selector}]`, ...args); -}); - + return cy.get(`[data-test=${selector}]`, ...args) +}) Cypress.Commands.add("getBySelLike", (selector, ...args) => { - return cy.get(`[data-test*=${selector}]`, ...args); -}); + return cy.get(`[data-test*=${selector}]`, ...args) +}) -Cypress.Commands.add("signup", () => { - const log = Cypress.log({ - name: "signup", - displayName: "signup", - message: [`Signup new account`], - // @ts-ignore - autoEnd: false, - }); +// Define the custom Cypress command in your Cypress support/commands.ts file +// commands.ts +Cypress.Commands.add('dragTo', (sourceElement: string, targetElement: string) => { + cy.get(sourceElement).then(() => { + cy.get(targetElement).then(($targetElement) => { + const targetOffset = $targetElement.offset(); + const targetWidth = $targetElement.width(); + const targetHeight = $targetElement.height(); - return cy - .window({ log: false }) - .its("SignupService", { log: false }) - .then((signup) => { - const workspaceName = faker.company.companyName(); - const userName = faker.name.findName(); - const userEmail = faker.internet.email(); - const userPassword = "snakes"; - const signupSecret = "cool-steam"; - const request = { - workspaceName, - userName, - userEmail, - userPassword, - signupSecret, - }; - cy.wrap(request).as("nw"); - return firstValueFrom(signup.createAccount(request)); + // Calculate the coordinates to move to the center of the target element + const clientX = targetOffset.left + targetWidth / 2; + const clientY = targetOffset.top + targetHeight / 2; + + // Trigger a drag and drop action + cy.get(sourceElement) + .trigger('mousedown', { button: 0 }) // Simulate mouse down event + .trigger('mousemove', { clientX: clientX, clientY: clientY }) // Move the object to a new position + .trigger('mouseup') // Simulate mouse up event }) - .then((response) => { - log.set({ - consoleProps() { - return response; - }, - }); - log.end(); - }); + }) }); -Cypress.Commands.add("signupAndLogin", () => { - const log = Cypress.log({ - name: "signup", - displayName: "signup and login", - message: [`Signup new account`], - // @ts-ignore - autoEnd: false, - }); - cy.signup(); - return cy.get("@nw").then((ctx) => { - return cy - .window() - .its("SessionService") - .then((SessionService) => { - return firstValueFrom( - SessionService.login({ - workspaceName: ctx.workspaceName, - userEmail: ctx.userEmail, - userPassword: ctx.userPassword, - }), - ); - }) - .then((response) => { - log.set({ - consoleProps() { - return response; - }, - }); - log.end(); - }); - }); -}); -export interface TestCtx { - workspace: Workspace; - workspace: Workspace; - user: User; - key_pair: PublicKey; -} + diff --git a/app/web/cypress/support/index.ts b/app/web/cypress/support/e2e.ts similarity index 75% rename from app/web/cypress/support/index.ts rename to app/web/cypress/support/e2e.ts index 413b0ecfa5..544eee6ffe 100644 --- a/app/web/cypress/support/index.ts +++ b/app/web/cypress/support/e2e.ts @@ -1,5 +1,5 @@ // *********************************************************** -// This example support/index.js is processed and +// This example support/e2e.ts is processed and // loaded automatically before your test files. // // This is a great place to put global configuration and @@ -13,5 +13,5 @@ // https://on.cypress.io/configuration // *********************************************************** -// Import commands.js using ES2015 syntax: -import "./commands"; +// When a command from ./commands is ready to use, import with `import './commands'` syntax +import './commands'; \ No newline at end of file diff --git a/app/web/cypress/tsconfig.json b/app/web/cypress/tsconfig.json index bf1ad3fbe8..6de634cb6e 100644 --- a/app/web/cypress/tsconfig.json +++ b/app/web/cypress/tsconfig.json @@ -1,7 +1,14 @@ { "compilerOptions": { - "lib": ["es2015", "dom"], - "types": ["cypress"], + "lib": [ + "es5", + "dom" + ], + "types": [ + "cypress", + "node", + "vite/client" + ], "isolatedModules": false, "allowJs": true, "noEmit": true, @@ -10,5 +17,10 @@ "allowSyntheticDefaultImports": true, "target": "es5", }, - "include": ["**/*.ts", "../src/**/*.ts"] -} + "include": [ + "**/*.ts", + "../src/**/*.ts", + "../cypress.d.ts" + ], + "extends": "../tsconfig.json", +} \ No newline at end of file diff --git a/app/web/package.json b/app/web/package.json index d9cadb9339..1f544ce711 100644 --- a/app/web/package.json +++ b/app/web/package.json @@ -101,7 +101,8 @@ "@types/tinycolor2": "^1.4.3", "@types/validator": "^13.7.2", "@vitejs/plugin-vue": "^4.5.2", - "cypress": "^9.6.0", + "cypress": "^13.6.3", + "cypress-vite": "^1.5.0", "eslint": "^8.36.0", "faker": "^6.6.6", "unplugin-icons": "^0.17.1", diff --git a/app/web/src/components/AssetPalette.vue b/app/web/src/components/AssetPalette.vue index 5e2af7897a..600643bd84 100644 --- a/app/web/src/components/AssetPalette.vue +++ b/app/web/src/components/AssetPalette.vue @@ -42,6 +42,7 @@ v-for="(schema, schemaIndex) in category.schemas" :key="schemaIndex" class="select-none border-b-2 dark:border-neutral-600" + data-cy="asset_card" > = 6'} dependencies: aws-sign2: 0.7.0 @@ -1381,9 +1384,9 @@ packages: json-stringify-safe: 5.0.1 mime-types: 2.1.35 performance-now: 2.1.0 - qs: 6.5.3 + qs: 6.10.4 safe-buffer: 5.2.1 - tough-cookie: 2.5.0 + tough-cookie: 4.1.3 tunnel-agent: 0.6.0 uuid: 8.3.2 dev: true @@ -4275,10 +4278,6 @@ packages: form-data: 3.0.1 dev: true - /@types/node@14.18.33: - resolution: {integrity: sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==} - dev: true - /@types/node@18.15.11: resolution: {integrity: sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==} @@ -6319,6 +6318,7 @@ packages: dependencies: function-bind: 1.1.2 get-intrinsic: 1.1.3 + dev: true /call-bind@1.0.5: resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} @@ -6326,7 +6326,6 @@ packages: function-bind: 1.1.2 get-intrinsic: 1.2.2 set-function-length: 1.1.1 - dev: true /call-me-maybe@1.0.2: resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} @@ -6864,8 +6863,8 @@ packages: engines: {node: '>= 6'} dev: true - /commander@5.1.0: - resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} + /commander@6.2.1: + resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} engines: {node: '>= 6'} dev: true @@ -7261,15 +7260,26 @@ packages: resolution: {integrity: sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A==} dev: true - /cypress@9.7.0: - resolution: {integrity: sha512-+1EE1nuuuwIt/N1KXRR2iWHU+OiIt7H28jJDyyI4tiUftId/DrXYEwoDa5+kH2pki1zxnA0r6HrUGHV5eLbF5Q==} - engines: {node: '>=12.0.0'} + /cypress-vite@1.5.0(vite@5.0.10): + resolution: {integrity: sha512-vvTMqJZgI3sN2ylQTi4OQh8LRRjSrfrIdkQD5fOj+EC/e9oHkxS96lif1SyDF1PwailG1tnpJE+VpN6+AwO/rg==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 + dependencies: + chokidar: 3.5.3 + debug: 4.3.4 + vite: 5.0.10(@types/node@18.15.11)(less@4.1.3) + transitivePeerDependencies: + - supports-color + dev: true + + /cypress@13.6.3: + resolution: {integrity: sha512-d/pZvgwjAyZsoyJ3FOsJT5lDsqnxQ/clMqnNc++rkHjbkkiF2h9s0JsZSyyH4QXhVFW3zPFg82jD25roFLOdZA==} + engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0} hasBin: true requiresBuild: true dependencies: - '@cypress/request': 2.88.10 + '@cypress/request': 3.0.1 '@cypress/xvfb': 1.2.4(supports-color@8.1.1) - '@types/node': 14.18.33 '@types/sinonjs__fake-timers': 8.1.1 '@types/sizzle': 2.3.3 arch: 2.2.0 @@ -7281,12 +7291,12 @@ packages: check-more-types: 2.24.0 cli-cursor: 3.1.0 cli-table3: 0.6.3 - commander: 5.1.0 + commander: 6.2.1 common-tags: 1.8.2 dayjs: 1.11.6 debug: 4.3.4(supports-color@8.1.1) enquirer: 2.3.6 - eventemitter2: 6.4.9 + eventemitter2: 6.4.7 execa: 4.1.0 executable: 4.1.1 extract-zip: 2.0.1(supports-color@8.1.1) @@ -7299,12 +7309,13 @@ packages: listr2: 3.14.0(enquirer@2.3.6) lodash: 4.17.21 log-symbols: 4.1.0 - minimist: 1.2.7 + minimist: 1.2.8 ospath: 1.2.2 pretty-bytes: 5.6.0 + process: 0.11.10 proxy-from-env: 1.0.0 request-progress: 3.0.0 - semver: 7.3.8 + semver: 7.5.4 supports-color: 8.1.1 tmp: 0.2.1 untildify: 4.0.0 @@ -7606,7 +7617,6 @@ packages: get-intrinsic: 1.2.2 gopd: 1.0.1 has-property-descriptors: 1.0.0 - dev: true /define-lazy-prop@2.0.0: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} @@ -9002,8 +9012,8 @@ packages: engines: {node: '>=6'} dev: true - /eventemitter2@6.4.9: - resolution: {integrity: sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==} + /eventemitter2@6.4.7: + resolution: {integrity: sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==} dev: true /eventemitter3@4.0.7: @@ -9996,6 +10006,7 @@ packages: function-bind: 1.1.2 has: 1.0.3 has-symbols: 1.0.3 + dev: true /get-intrinsic@1.2.2: resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} @@ -10004,7 +10015,6 @@ packages: has-proto: 1.0.1 has-symbols: 1.0.3 hasown: 2.0.0 - dev: true /get-package-type@0.1.0: resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} @@ -10300,7 +10310,6 @@ packages: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: get-intrinsic: 1.2.2 - dev: true /got@11.8.6: resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} @@ -10409,13 +10418,11 @@ packages: /has-property-descriptors@1.0.0: resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} dependencies: - get-intrinsic: 1.1.3 - dev: true + get-intrinsic: 1.2.2 /has-proto@1.0.1: resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} engines: {node: '>= 0.4'} - dev: true /has-symbol-support-x@1.4.2: resolution: {integrity: sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==} @@ -10503,7 +10510,6 @@ packages: engines: {node: '>= 0.4'} dependencies: function-bind: 1.1.2 - dev: true /he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} @@ -13499,6 +13505,10 @@ packages: /minimist@1.2.7: resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + /minipass-collect@1.0.2: resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} engines: {node: '>= 8'} @@ -14291,10 +14301,10 @@ packages: /object-inspect@1.12.2: resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==} + dev: true /object-inspect@1.13.1: resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - dev: true /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} @@ -15551,7 +15561,6 @@ packages: /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - dev: false /pupa@3.1.0: resolution: {integrity: sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==} @@ -15560,16 +15569,18 @@ packages: escape-goat: 4.0.0 dev: true - /qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + /qs@6.10.4: + resolution: {integrity: sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==} engines: {node: '>=0.6'} dependencies: side-channel: 1.0.4 + dev: true - /qs@6.5.3: - resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} + /qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} engines: {node: '>=0.6'} - dev: true + dependencies: + side-channel: 1.0.4 /query-string@5.1.1: resolution: {integrity: sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==} @@ -16428,7 +16439,6 @@ packages: get-intrinsic: 1.2.2 gopd: 1.0.1 has-property-descriptors: 1.0.0 - dev: true /set-function-name@2.0.1: resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} @@ -16477,9 +16487,9 @@ packages: /side-channel@1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.1.3 - object-inspect: 1.12.2 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + object-inspect: 1.13.1 /siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -17701,22 +17711,24 @@ packages: resolution: {integrity: sha512-2Ulkc8T7mXJ2l0W476YC/A209PR38Nw8PuaCNtk9uI3t1zzFdGQeWYGQvmj2PZkVvRC/Yoi4xQKMRnWc/N29tQ==} dev: true - /tough-cookie@2.5.0: - resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} - engines: {node: '>=0.8'} + /tough-cookie@4.1.2: + resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==} + engines: {node: '>=6'} dependencies: psl: 1.9.0 punycode: 2.1.1 - dev: true + universalify: 0.2.0 + url-parse: 1.5.10 - /tough-cookie@4.1.2: - resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==} + /tough-cookie@4.1.3: + resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} engines: {node: '>=6'} dependencies: psl: 1.9.0 - punycode: 2.1.1 + punycode: 2.3.1 universalify: 0.2.0 url-parse: 1.5.10 + dev: true /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}