diff --git a/.gitignore b/.gitignore index ca2a5b7af..47b17bbac 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,8 @@ coverage/ \#*\# .\#* docker-compose.override.yml + +# cypress e2e artifacts +e2e/**/cypress/videos/ +e2e/**/cypress/screenshots/ +e2e/**/cypress/downloads/ diff --git a/docker-compose.e2e.yaml b/docker-compose.e2e.yaml new file mode 100644 index 000000000..5b8e37daf --- /dev/null +++ b/docker-compose.e2e.yaml @@ -0,0 +1,171 @@ +# EDR Freight — ephemeral Cypress e2e stack. +# Fully isolated from dev: own ports, own throwaway Postgres (tmpfs — data +# vanishes on `down`), seeded test users. Requires the same .npmrc as the main +# docker-compose.yaml (GitHub Packages auth for @tria-plc). +# +# Up (build + wait healthy): docker compose -f docker-compose.e2e.yaml up -d --build --wait +# Headless run in container: docker compose -f docker-compose.e2e.yaml --profile cypress run --rm cypress +# Interactive from host: pnpm --filter @edr/freight-e2e cy:open +# Teardown: docker compose -f docker-compose.e2e.yaml down -v --remove-orphans +# +# Host ports (chosen to never collide with the dev stack): +# freight-api 3101 portal 5273 backoffice 5283 +# postgres 5533 minio 9310 (console 9311) +name: edr-freight-e2e + +services: + postgres-freight-e2e: + image: postgres:16-alpine + environment: + POSTGRES_DB: edr_freight_e2e + POSTGRES_USER: edr_e2e + POSTGRES_PASSWORD: edr_e2e + tmpfs: + - /var/lib/postgresql/data + ports: + - "5533:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U edr_e2e -d edr_freight_e2e"] + interval: 2s + timeout: 3s + retries: 30 + + minio-e2e: + image: minio/minio:latest + command: server /data --console-address ":9001" + environment: + MINIO_ROOT_USER: e2e-minio + MINIO_ROOT_PASSWORD: e2e-minio-secret + tmpfs: + - /data + ports: + - "9310:9000" + - "9311:9001" + healthcheck: + test: ["CMD", "mc", "ready", "local"] + interval: 5s + timeout: 5s + retries: 12 + + freight-api-e2e: + build: + context: . + dockerfile: apps/edr-freight-api/Dockerfile + secrets: + - npmrc + depends_on: + postgres-freight-e2e: + condition: service_healthy + minio-e2e: + condition: service_healthy + environment: + PORT: "3001" + DB_HOST: postgres-freight-e2e + DB_PORT: "5432" + DB_USER: edr_e2e + DB_PASSWORD: edr_e2e + DB_NAME: edr_freight_e2e + # e2e-only secrets — never reuse outside this stack + JWT_SECRET: e2e-jwt-secret + JWT_ACCESS_TOKEN_SECRET: e2e-access-secret + JWT_REFRESH_TOKEN_SECRET: e2e-refresh-secret + JWT_EXPIRES_IN: 1d + JWT_ACCESS_TOKEN_EXPIRES: 1d + JWT_REFRESH_TOKEN_EXPIRES: 7d + SERVICE_AUTH_TOKEN: e2e-service-token + # Org/unit/position boot seeders (env-gated in app code). Test USERS are + # NOT seeded by the API — Cypress inserts them via + # e2e/freight/cypress/fixtures/seed-users.sql before specs run. + SEED_EDR_ORG: "true" + SUPER_ADMIN_EMAIL: superadmin@tria.com + SUPER_ADMIN_PHONE: "+251900000000" + # Object storage + MINIO_ENDPOINT: minio-e2e + MINIO_PORT: "9000" + MINIO_USE_SSL: "false" + MINIO_ACCESS_KEY: e2e-minio + MINIO_SECRET_KEY: e2e-minio-secret + MINIO_REGION: us-east-1 + # External integrations off + RABBITMQ_ENABLED: "false" + FAYDA_ENABLED: "false" + FREIGHT_PORTAL_URL: http://localhost:5273 + ports: + - "3101:3001" + healthcheck: + # Boot runs 240+ migrations + seeders on first start — generous start_period. + test: + [ + "CMD", + "node", + "-e", + "fetch('http://localhost:3001/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))", + ] + interval: 5s + timeout: 5s + retries: 12 + start_period: 180s + + freight-portal-e2e: + build: + context: . + dockerfile: infrastructure/docker/Dockerfile.web + args: + TURBO_FILTER: "@edr/freight-portal" + APP_PATH: apps/edr-freight-web/portal + # Baked at build time: browser (host or host-networked cypress + # container) reaches the API through the published host port. + VITE_API_URL: http://localhost:3101 + VITE_BASE_API_URL: http://localhost:3101 + VITE_USER_MANAGEMENT_BASE: /_um + VITE_GOOGLE_MAPS_API_KEY: "" + VITE_POSTHOG_KEY: "" + VITE_POSTHOG_HOST: "" + secrets: + - npmrc + ports: + - "5273:80" + + freight-backoffice-e2e: + build: + context: . + dockerfile: infrastructure/docker/Dockerfile.web + args: + TURBO_FILTER: "@edr/freight-backoffice" + APP_PATH: apps/edr-freight-web/backoffice + VITE_API_URL: http://localhost:3101 + VITE_BASE_API_URL: http://localhost:3101 + VITE_USER_MANAGEMENT_BASE: /_um + VITE_GOOGLE_MAPS_API_KEY: "" + VITE_POSTHOG_KEY: "" + VITE_POSTHOG_HOST: "" + secrets: + - npmrc + ports: + - "5283:80" + + # Headless runner — opt-in via `--profile cypress`. host network so the + # in-container browser uses the exact same localhost URLs as `cypress open` + # on the host (Linux only; on macOS/Windows run Cypress from the host). + cypress: + # Keep in sync with the cypress version in e2e/freight/package.json. + image: cypress/included:${CYPRESS_VERSION:-15.18.1} + profiles: ["cypress"] + network_mode: host + depends_on: + freight-api-e2e: + condition: service_healthy + working_dir: /repo/e2e/freight + # NOTE: host network shares the abstract X-socket namespace with the host. + # Cypress spawns its Xvfb on :99 — run only ONE cypress container at a + # time, and don't run it on a host whose X server occupies :99. + entrypoint: ["cypress", "run", "--browser", "chrome"] + environment: + CI: "true" + E2E_DB_URL: postgres://edr_e2e:edr_e2e@localhost:5533/edr_freight_e2e + volumes: + - .:/repo + +secrets: + npmrc: + file: .npmrc diff --git a/e2e/freight/README.md b/e2e/freight/README.md new file mode 100644 index 000000000..6cefcdcfa --- /dev/null +++ b/e2e/freight/README.md @@ -0,0 +1,80 @@ +# @edr/freight-e2e — Cypress e2e suite for the freight system + +Containerized, fully isolated e2e environment: throwaway Postgres (tmpfs), +MinIO, freight-api, portal, and backoffice — plus a Cypress runner that works +both headless-in-Docker and interactively from the host against the same URLs. + +## Stack (`docker-compose.e2e.yaml`, project name `edr-freight-e2e`) + +| Service | Host port | Notes | +| ----------------------- | --------- | ---------------------------------------------- | +| `freight-api-e2e` | 3101 | migrations + seeders run at boot | +| `freight-portal-e2e` | 5273 | nginx static build, API baked to `:3101` | +| `freight-backoffice-e2e`| 5283 | nginx static build, API baked to `:3101` | +| `postgres-freight-e2e` | 5533 | `edr_freight_e2e`, tmpfs — gone on `down` | +| `minio-e2e` | 9310/9311 | object storage for file features | +| `cypress` | (host net)| profile `cypress`, headless chrome | + +Ports deliberately avoid the dev stack (3001/5173/5183/5433). The dev database +is never touched. + +## Usage (from repo root) + +```bash +pnpm e2e:freight:up # build + start stack, wait for healthchecks +pnpm e2e:freight:open # interactive Cypress on the host +pnpm e2e:freight:run # headless run from the host +pnpm e2e:freight:ci # headless run inside the cypress container +pnpm e2e:freight:down # teardown, drop all data +``` + +First `up` is slow (image builds + 240 migrations + seeders — healthcheck +allows 3 min). Requires the same root `.npmrc` (GitHub Packages auth for +`@tria-plc`) as the main compose file. + +The `cypress` service uses `network_mode: host` (Linux). On macOS/Windows run +Cypress from the host (`e2e:freight:open` / `e2e:freight:run`) instead of the +container. + +## Test users + +Inserted by Cypress itself — a global `before()` hook runs +`cy.task("db:seedUsers")`, which executes +`cypress/fixtures/seed-users.sql` (idempotent, pre-hashed argon2 passwords) +against the e2e database. No API code is involved; the app's user seeders +stay disabled. The API's always-on boot seeders must have run first +(org/unit/positions) — guaranteed once `freight-api-e2e` is healthy. + +- Staff (backoffice): `linestaff|chief|director|ceo|marketer|operation|gl-et|gl-dj@edr.local` + — password `password@tria` +- Customers (portal): `user@gmail.com`, `user2@gmail.com` + — password `12345678` + +Full map in `cypress/fixtures/users.json`. + +## Conventions + +- **Programmatic login** everywhere except the two dedicated UI-login specs: + `cy.loginBackoffice(email?)` / `cy.loginPortal(email?)` — `cy.session`-cached + (across specs), `POST /api/auth/login`, sets the `auth-token` / + `refresh-token` cookies the apps read. +- **Origins**: `baseUrl` is the backoffice (5283). Portal specs `cy.visit` + the absolute portal URL; a test that touches *both* apps wraps portal steps + in `cy.origin()` (different port = different origin). Cookies ignore ports — + always call the matching login command right before switching apps so + `cy.session` restores the right cookie snapshot. +- **DB access**: `cy.task("db:query", { sql, params })` runs SQL against the + e2e database (`E2E_DB_URL`, default `localhost:5533`). Use for seeding + edge-case data and asserting side effects — it can never reach the dev DB. +- **Spec layout**: + - `cypress/e2e/api/` — API contract via `cy.request` (no browser) + - `cypress/e2e/backoffice/` — staff app + - `cypress/e2e/portal/` — customer app + - `cypress/e2e/flows/` — cross-app journeys (both directions) + +## Extending + +Deep module flows (booking wizard → staff approval → scheduling → billing) +belong in `flows/`. Pattern: arrange via API/`db:query`, act through the UI of +one app, assert through the UI of the other + a `db:query` cross-check. Prefer +adding `data-testid` attributes to app code over brittle text selectors. diff --git a/e2e/freight/cypress.config.ts b/e2e/freight/cypress.config.ts new file mode 100644 index 000000000..56c0f758a --- /dev/null +++ b/e2e/freight/cypress.config.ts @@ -0,0 +1,80 @@ +import { defineConfig } from "cypress"; +import { readFileSync } from "node:fs"; +import { join } from "node:path"; +import { Client } from "pg"; + +/** + * Freight e2e suite. Three origins: + * backoffice http://localhost:5283 (baseUrl — most specs live here) + * portal http://localhost:5273 (env.portalUrl; portal specs cy.visit it, + * cross-app flows reach it via cy.origin) + * api http://localhost:3101 (env.apiUrl; cy.request only) + * + * All URLs are host-published ports from docker-compose.e2e.yaml. The cypress + * container in that compose file runs with network_mode: host, so the same + * localhost URLs work identically for `cypress open` on the host and for the + * containerized headless run. + */ +export default defineConfig({ + e2e: { + baseUrl: process.env.CYPRESS_BASE_URL ?? "http://localhost:5283", + specPattern: "cypress/e2e/**/*.cy.ts", + supportFile: "cypress/support/e2e.ts", + video: process.env.CI === "true" || process.env.CYPRESS_VIDEO === "true", + screenshotOnRunFailure: true, + viewportWidth: 1440, + viewportHeight: 900, + defaultCommandTimeout: 10000, + requestTimeout: 15000, + retries: { runMode: 1, openMode: 0 }, + env: { + apiUrl: process.env.CYPRESS_API_URL ?? "http://localhost:3101", + portalUrl: process.env.CYPRESS_PORTAL_URL ?? "http://localhost:5273", + backofficeUrl: process.env.CYPRESS_BASE_URL ?? "http://localhost:5283", + // Staff users: DEFAULT_PASSWORD from docker-compose.e2e.yaml. + defaultPassword: process.env.CYPRESS_DEFAULT_PASSWORD ?? "password@tria", + // Demo portal users: hardcoded in DemoUsersSeeder. + demoPassword: "12345678", + }, + setupNodeEvents(on) { + const dbUrl = + process.env.E2E_DB_URL ?? + "postgres://edr_e2e:edr_e2e@localhost:5533/edr_freight_e2e"; + + on("task", { + /** Run an arbitrary SQL statement against the ephemeral e2e database. */ + async "db:query"({ sql, params = [] }: { sql: string; params?: unknown[] }) { + const client = new Client({ connectionString: dbUrl }); + await client.connect(); + try { + const result = await client.query(sql, params as never[]); + return { rowCount: result.rowCount, rows: result.rows }; + } finally { + await client.end(); + } + }, + + /** + * Seed the test users (staff + demo) directly in SQL. The API's + * user seeders are disabled in app code, so the fixture replicates + * their output. Idempotent — safe to run before every spec file. + */ + async "db:seedUsers"() { + // cwd = the e2e/freight project root when Cypress runs. + const sql = readFileSync( + join(process.cwd(), "cypress", "fixtures", "seed-users.sql"), + "utf8", + ); + const client = new Client({ connectionString: dbUrl }); + await client.connect(); + try { + await client.query(sql); + return true; + } finally { + await client.end(); + } + }, + }); + }, + }, +}); diff --git a/e2e/freight/cypress/e2e/api/health-and-auth.cy.ts b/e2e/freight/cypress/e2e/api/health-and-auth.cy.ts new file mode 100644 index 000000000..c183a11df --- /dev/null +++ b/e2e/freight/cypress/e2e/api/health-and-auth.cy.ts @@ -0,0 +1,79 @@ +/** + * API contract smoke — no browser, pure cy.request against freight-api. + * Verifies the containerized stack booted: migrations ran, seeders ran, + * auth issues tokens. + */ +const api = () => Cypress.env("apiUrl") as string; + +describe("freight-api: health + auth contract", () => { + it("GET /api/health responds", () => { + cy.request(`${api()}/api/health`).its("status").should("eq", 200); + }); + + it("rejects bad credentials", () => { + cy.request({ + method: "POST", + url: `${api()}/api/auth/login`, + body: { email: "nobody@edr.local", password: "wrong-password" }, + failOnStatusCode: false, + }) + .its("status") + .should("be.oneOf", [400, 401, 404]); + }); + + it("logs in every seeded staff user", () => { + cy.fixture("users.json").then((users) => { + Object.values<{ email: string }>(users.staff).forEach(({ email }) => { + cy.apiLogin(email); + }); + }); + }); + + it("staff token can read /api/me", () => { + cy.apiLogin("ceo@edr.local").then(({ token }) => { + cy.request({ + url: `${api()}/api/me`, + headers: { Authorization: `Bearer ${token}` }, + }).then((response) => { + expect(response.status).to.eq(200); + }); + }); + }); + + it("refresh-token rotates the session", () => { + cy.apiLogin("chief@edr.local").then(({ refreshToken }) => { + cy.request("POST", `${api()}/api/auth/refresh-token`, { refreshToken }) + .its("body.token") + .should("be.a", "string"); + }); + }); + + it("demo portal users are seeded", () => { + // DemoUsersSeeder hardcodes this password (staff users use DEFAULT_PASSWORD) + cy.apiLogin("user@gmail.com", Cypress.env("demoPassword")); + cy.apiLogin("user2@gmail.com", Cypress.env("demoPassword")); + }); +}); + +describe("freight-api: seeded database", () => { + it("migrations table is populated", () => { + cy.task<{ rowCount: number }>("db:query", { + sql: "select count(*)::int as count from migrations", + }).then(({ rows }: any) => { + expect(rows[0].count).to.be.greaterThan(100); + }); + }); + + it("staff users exist with credentials", () => { + cy.task("db:query", { + sql: `select u.email from iam.users u + join iam.user_credentials c on c.user_id = u.id + where u.email like '%@edr.local' order by u.email`, + }).then(({ rows }: any) => { + const emails = rows.map((row: { email: string }) => row.email); + expect(emails).to.include.members(["ceo@edr.local", "linestaff@edr.local"]); + }); + }); +}); + +export {}; diff --git a/e2e/freight/cypress/e2e/backoffice/login.cy.ts b/e2e/freight/cypress/e2e/backoffice/login.cy.ts new file mode 100644 index 000000000..0a729bdae --- /dev/null +++ b/e2e/freight/cypress/e2e/backoffice/login.cy.ts @@ -0,0 +1,41 @@ +/** + * The one UI-driven login spec for backoffice — every other spec uses the + * programmatic cy.loginBackoffice() session. + * Login form: apps/edr-freight-web/backoffice/src/pages/auth/LoginPage.tsx + * (Mantine inputs, matched by placeholder). + */ +describe("backoffice: UI login", () => { + it("redirects unauthenticated users to /auth", () => { + cy.clearCookies(); + cy.visit("/dashboard/overview"); + cy.location("pathname").should("eq", "/auth"); + }); + + it("logs in via the form and lands on the dashboard", () => { + cy.clearCookies(); + cy.visit("/auth"); + cy.get('input[placeholder="name@company.com or 09XXXXXXXX"]').type("ceo@edr.local"); + cy.get('input[placeholder="Enter your password"]').type( + Cypress.env("defaultPassword"), + { log: false }, + ); + cy.get('button[type="submit"]').click(); + + cy.location("pathname", { timeout: 20000 }).should("match", /^\/dashboard/); + cy.getCookie("auth-token").should("exist"); + cy.getCookie("refresh-token").should("exist"); + }); + + it("shows an error for wrong credentials and stays on /auth", () => { + cy.clearCookies(); + cy.visit("/auth"); + cy.get('input[placeholder="name@company.com or 09XXXXXXXX"]').type("ceo@edr.local"); + cy.get('input[placeholder="Enter your password"]').type("definitely-wrong"); + cy.get('button[type="submit"]').click(); + + cy.location("pathname").should("eq", "/auth"); + cy.getCookie("auth-token").should("not.exist"); + }); +}); + +export {}; diff --git a/e2e/freight/cypress/e2e/backoffice/smoke.cy.ts b/e2e/freight/cypress/e2e/backoffice/smoke.cy.ts new file mode 100644 index 000000000..db3086e71 --- /dev/null +++ b/e2e/freight/cypress/e2e/backoffice/smoke.cy.ts @@ -0,0 +1,49 @@ +/** + * Route-level smoke over the backoffice shell: each key module page loads + * without bouncing back to /auth and without an unhandled crash. Deep + * per-module behavior belongs in dedicated specs — this catches the broad + * "page is broken / route is dead / guard rejects seeded role" class. + * Routes from apps/edr-freight-web/backoffice/src/App.tsx. + */ +const ROUTES = [ + "/dashboard/overview", + "/dashboard/booking-requests", + "/dashboard/customers", + "/dashboard/invoices", + "/dashboard/contract-requests", + "/dashboard/shipment-requests", + "/dashboard/profile", +]; + +describe("backoffice: route smoke (ceo)", () => { + beforeEach(() => { + cy.loginBackoffice("ceo@edr.local"); + }); + + ROUTES.forEach((route) => { + it(`renders ${route}`, () => { + cy.visit(route); + cy.location("pathname").should("not.eq", "/auth"); + cy.location("pathname").should("contain", "/dashboard"); + cy.get("#root").should("not.be.empty"); + }); + }); +}); + +describe("backoffice: role-based access", () => { + it("line staff can reach the dashboard shell", () => { + cy.loginBackoffice("linestaff@edr.local"); + cy.visit("/dashboard/overview"); + cy.location("pathname").should("not.eq", "/auth"); + cy.get("#root").should("not.be.empty"); + }); + + it("operations officer can reach the dashboard shell", () => { + cy.loginBackoffice("operation@edr.local"); + cy.visit("/dashboard/overview"); + cy.location("pathname").should("not.eq", "/auth"); + cy.get("#root").should("not.be.empty"); + }); +}); + +export {}; diff --git a/e2e/freight/cypress/e2e/flows/cross-app.cy.ts b/e2e/freight/cypress/e2e/flows/cross-app.cy.ts new file mode 100644 index 000000000..954ed4762 --- /dev/null +++ b/e2e/freight/cypress/e2e/flows/cross-app.cy.ts @@ -0,0 +1,69 @@ +/** + * Cross-app flow: same business objects seen from both directions — + * customer (portal, port 5273) and staff (backoffice, port 5283 = baseUrl). + * Different ports = different origins, so portal steps inside a test that + * also touches backoffice run inside cy.origin(). + * + * Cookie caveat: cookies ignore ports, so both apps share the localhost + * cookie jar. Always call the matching login command immediately before + * switching apps — cy.session restores the right cookie snapshot. + * + * This spec is the template for full journeys (booking → approval → + * scheduling → billing). It verifies both sides of the fence against + * seeded data via UI + API cross-checks. + */ +const portal = () => Cypress.env("portalUrl") as string; +const api = () => Cypress.env("apiUrl") as string; + +describe("flow: customer and staff see the same world", () => { + it("staff views booking requests, customer views bookings", () => { + // Staff side on the primary origin (baseUrl) first — the first origin a + // test visits becomes primary; every other origin needs cy.origin(). + cy.loginBackoffice("ceo@edr.local"); + cy.visit("/dashboard/booking-requests"); + cy.location("pathname").should("eq", "/dashboard/booking-requests"); + cy.get("#root").should("not.be.empty"); + + // Customer side — switch session first, then enter the portal origin. + cy.loginPortal("user@gmail.com"); + cy.origin(portal(), () => { + cy.visit("/bookings"); + cy.location("pathname").should("not.eq", "/login"); + cy.get("#root").should("not.be.empty"); + }); + }); + + it("staff and customer both resolve their own /api/me identity", () => { + cy.apiLogin("ceo@edr.local").then(({ token }) => { + cy.request({ + url: `${api()}/api/me`, + headers: { Authorization: `Bearer ${token}` }, + }) + .its("status") + .should("eq", 200); + }); + cy.apiLogin("user@gmail.com", Cypress.env("demoPassword")).then(({ token }) => { + cy.request({ + url: `${api()}/api/me`, + headers: { Authorization: `Bearer ${token}` }, + }) + .its("status") + .should("eq", 200); + }); + }); + + it("cy.origin: staff dashboard then portal in a single test", () => { + cy.loginBackoffice("ceo@edr.local"); + cy.visit("/dashboard/overview"); + cy.get("#root").should("not.be.empty"); + + cy.loginPortal("user@gmail.com"); + cy.origin(Cypress.env("portalUrl") as string, () => { + cy.visit("/portal"); + cy.location("pathname").should("not.eq", "/login"); + cy.get("#root").should("not.be.empty"); + }); + }); +}); + +export {}; diff --git a/e2e/freight/cypress/e2e/portal/login.cy.ts b/e2e/freight/cypress/e2e/portal/login.cy.ts new file mode 100644 index 000000000..c26365a22 --- /dev/null +++ b/e2e/freight/cypress/e2e/portal/login.cy.ts @@ -0,0 +1,36 @@ +/** + * UI login for the customer portal (seeded demo user). + * Form: apps/edr-freight-web/portal/src/pages/accounts/LoginPage.tsx. + * Portal is a different origin (port 5273), so specs visit it via absolute + * URL — each test here stays on that single origin, no cy.origin needed. + */ +const portal = () => Cypress.env("portalUrl") as string; + +describe("portal: UI login", () => { + it("logs in via the form", () => { + cy.clearCookies(); + cy.visit(`${portal()}/login`); + cy.get('input[placeholder="name@company.com or 09XXXXXXXX"]').type("user@gmail.com"); + cy.get('input[placeholder="Enter your password"]').type( + Cypress.env("demoPassword"), + { log: false }, + ); + cy.get('button[type="submit"]').click(); + + cy.location("pathname", { timeout: 20000 }).should("not.eq", "/login"); + cy.getCookie("auth-token").should("exist"); + }); + + it("rejects wrong credentials", () => { + cy.clearCookies(); + cy.visit(`${portal()}/login`); + cy.get('input[placeholder="name@company.com or 09XXXXXXXX"]').type("user@gmail.com"); + cy.get('input[placeholder="Enter your password"]').type("definitely-wrong"); + cy.get('button[type="submit"]').click(); + + cy.location("pathname").should("eq", "/login"); + cy.getCookie("auth-token").should("not.exist"); + }); +}); + +export {}; diff --git a/e2e/freight/cypress/e2e/portal/smoke.cy.ts b/e2e/freight/cypress/e2e/portal/smoke.cy.ts new file mode 100644 index 000000000..5372d7359 --- /dev/null +++ b/e2e/freight/cypress/e2e/portal/smoke.cy.ts @@ -0,0 +1,29 @@ +/** + * Route-level smoke over the customer portal. + * Routes from apps/edr-freight-web/portal/src/App.tsx. + */ +const portal = () => Cypress.env("portalUrl") as string; + +const ROUTES = ["/portal", "/bookings", "/contracts", "/billing", "/tracking"]; + +describe("portal: route smoke (demo customer)", () => { + beforeEach(() => { + cy.loginPortal("user@gmail.com"); + }); + + ROUTES.forEach((route) => { + it(`renders ${route}`, () => { + cy.visit(`${portal()}${route}`); + cy.location("pathname").should("not.eq", "/login"); + cy.get("#root").should("not.be.empty"); + }); + }); + + it("new booking wizard opens", () => { + cy.visit(`${portal()}/bookings/new`); + cy.location("pathname").should("eq", "/bookings/new"); + cy.get("#root").should("not.be.empty"); + }); +}); + +export {}; diff --git a/e2e/freight/cypress/fixtures/seed-users.sql b/e2e/freight/cypress/fixtures/seed-users.sql new file mode 100644 index 000000000..a9f60b286 --- /dev/null +++ b/e2e/freight/cypress/fixtures/seed-users.sql @@ -0,0 +1,130 @@ +-- Test users for the freight e2e stack — replicates what the (disabled) +-- FreightStaffUsersSeeder + DemoUsersSeeder would write, without touching +-- API code. Idempotent: every insert is guarded by WHERE NOT EXISTS. +-- +-- Prerequisites (created by the API's always-on boot seeders): +-- iam.organizations key='edr_freight', iam.units key='edr_freight_app', +-- iam.positions keys ceo/chief/director/marketer/operation/ethiopian_gl/djibouti_gl. +-- +-- Passwords are pre-hashed (argon2id): +-- staff (@edr.local) → password@tria +-- demo (gmail.com) → 12345678 + +-- ── Demo organization ──────────────────────────────────────────────────────── +insert into iam.organizations (id, name, key, is_super_admin, is_government_organization, status) +select gen_random_uuid(), '{"en":"Demo IAM"}'::jsonb, 'demo_iam', false, true, 'Active' +where not exists (select 1 from iam.organizations where key = 'demo_iam'); + +-- ── Roles ──────────────────────────────────────────────────────────────────── +insert into iam.roles (id, key, name) +select gen_random_uuid(), v.key, jsonb_build_object('en', v.name) +from (values + ('edr_line_staff', 'edr_line_staff'), + ('edr_org_manager', 'edr_org_manager'), + ('edr_director', 'edr_director'), + ('edr_ceo', 'edr_ceo'), + ('edr_marketing', 'edr_marketing'), + ('edr_operations_officer', 'edr_operations_officer'), + ('edr_gl_ethiopia', 'edr_gl_ethiopia'), + ('edr_gl_djibouti', 'edr_gl_djibouti'), + ('demo_user1', 'Demo User1'), + ('demo_user2', 'Demo User2') +) v(key, name) +where not exists (select 1 from iam.roles r where r.key = v.key); + +-- ── Demo permissions + role grants ─────────────────────────────────────────── +insert into iam.permissions (id, key, name) +select gen_random_uuid(), v.key, jsonb_build_object('en', v.name) +from (values + ('can:demo:user1', 'Can access demo user1'), + ('can:demo:user2', 'Can access demo user2') +) v(key, name) +where not exists (select 1 from iam.permissions p where p.key = v.key); + +insert into iam.role_permissions (id, role_id, permission_id) +select gen_random_uuid(), r.id, p.id +from (values ('demo_user1', 'can:demo:user1'), ('demo_user2', 'can:demo:user2')) v(role_key, perm_key) +join iam.roles r on r.key = v.role_key +join iam.permissions p on p.key = v.perm_key +where not exists ( + select 1 from iam.role_permissions rp where rp.role_id = r.id and rp.permission_id = p.id +); + +-- ── Users ──────────────────────────────────────────────────────────────────── +insert into iam.users (id, email, username, name, status, is_active, has_set_password, user_type) +select gen_random_uuid(), v.email, v.username, jsonb_build_object('en', v.display), + 'accepted', true, true, 'employee' +from (values + ('linestaff@edr.local', 'linestaff', 'linestaff'), + ('chief@edr.local', 'chief', 'chief'), + ('director@edr.local', 'director', 'director'), + ('ceo@edr.local', 'ceo', 'ceo'), + ('marketer@edr.local', 'marketer', 'marketer'), + ('operation@edr.local', 'operation', 'operation'), + ('gl-et@edr.local', 'gl_et', 'gl_et'), + ('gl-dj@edr.local', 'gl_dj', 'gl_dj'), + ('user@gmail.com', 'user', 'Demo User 1'), + ('user2@gmail.com', 'user2', 'Demo User 2') +) v(email, username, display) +where not exists (select 1 from iam.users u where u.email = v.email); + +-- ── Credentials ────────────────────────────────────────────────────────────── +insert into iam.user_credentials (id, user_id, password, is_active) +select gen_random_uuid(), u.id, + case when u.email like '%@edr.local' + then '$argon2id$v=19$m=65536,t=3,p=4$JFEcHu4Kp55fsrVDPbHDPg$0NfnGzaE39T/qdmzte73oCkohC0Ri+f8DcrvAF4kyH4' -- password@tria + else '$argon2id$v=19$m=65536,t=3,p=4$aBwVFf7I74pqSJqe9cBoig$gCIKa+6dCAb2X86G+0IjgPtil127cx6A6mwhvLj00Bw' -- 12345678 + end, + true +from iam.users u +where (u.email like '%@edr.local' or u.email in ('user@gmail.com', 'user2@gmail.com')) + and not exists (select 1 from iam.user_credentials c where c.user_id = u.id); + +-- ── User → role (staff under edr_freight, demo under demo_iam) ────────────── +insert into iam.user_roles (id, user_id, role_id, organization_id) +select gen_random_uuid(), u.id, r.id, o.id +from (values + ('linestaff@edr.local', 'edr_line_staff', 'edr_freight'), + ('chief@edr.local', 'edr_org_manager', 'edr_freight'), + ('director@edr.local', 'edr_director', 'edr_freight'), + ('ceo@edr.local', 'edr_ceo', 'edr_freight'), + ('marketer@edr.local', 'edr_marketing', 'edr_freight'), + ('operation@edr.local', 'edr_operations_officer', 'edr_freight'), + ('gl-et@edr.local', 'edr_gl_ethiopia', 'edr_freight'), + ('gl-dj@edr.local', 'edr_gl_djibouti', 'edr_freight'), + ('user@gmail.com', 'demo_user1', 'demo_iam'), + ('user2@gmail.com', 'demo_user2', 'demo_iam') +) v(email, role_key, org_key) +join iam.users u on u.email = v.email +join iam.roles r on r.key = v.role_key +join iam.organizations o on o.key = v.org_key +where not exists (select 1 from iam.user_roles ur where ur.user_id = u.id and ur.role_id = r.id); + +-- ── Staff employees + position assignment (drives permissions) ─────────────── +insert into iam.employees (id, is_current, status, name, organization_id, unit_id, user_id) +select gen_random_uuid(), true, 'pending', u.name, o.id, un.id, u.id +from iam.users u +join iam.organizations o on o.key = 'edr_freight' +join iam.units un on un.key = 'edr_freight_app' and un.organization_id = o.id +where u.email like '%@edr.local' + and not exists (select 1 from iam.employees e where e.user_id = u.id); + +insert into iam.employee_positions (id, is_delegate, is_current, status, unit_id, employee_id, position_id) +select gen_random_uuid(), false, true, 'APPROVED', un.id, e.id, p.id +from (values + ('linestaff@edr.local', 'operation'), + ('chief@edr.local', 'chief'), + ('director@edr.local', 'director'), + ('ceo@edr.local', 'ceo'), + ('marketer@edr.local', 'marketer'), + ('operation@edr.local', 'operation'), + ('gl-et@edr.local', 'ethiopian_gl'), + ('gl-dj@edr.local', 'djibouti_gl') +) v(email, position_key) +join iam.users u on u.email = v.email +join iam.employees e on e.user_id = u.id +join iam.units un on un.key = 'edr_freight_app' +join iam.positions p on p.key = v.position_key and p.unit_id = un.id +where not exists ( + select 1 from iam.employee_positions ep where ep.employee_id = e.id and ep.position_id = p.id +); diff --git a/e2e/freight/cypress/fixtures/users.json b/e2e/freight/cypress/fixtures/users.json new file mode 100644 index 000000000..88c56149f --- /dev/null +++ b/e2e/freight/cypress/fixtures/users.json @@ -0,0 +1,16 @@ +{ + "staff": { + "lineStaff": { "email": "linestaff@edr.local", "role": "edr_line_staff" }, + "chief": { "email": "chief@edr.local", "role": "edr_org_manager" }, + "director": { "email": "director@edr.local", "role": "edr_director" }, + "ceo": { "email": "ceo@edr.local", "role": "edr_ceo" }, + "marketer": { "email": "marketer@edr.local", "role": "edr_marketing" }, + "operation": { "email": "operation@edr.local", "role": "edr_operations_officer" }, + "glEthiopia": { "email": "gl-et@edr.local", "role": "edr_gl_ethiopia" }, + "glDjibouti": { "email": "gl-dj@edr.local", "role": "edr_gl_djibouti" } + }, + "customers": { + "demo1": { "email": "user@gmail.com" }, + "demo2": { "email": "user2@gmail.com" } + } +} diff --git a/e2e/freight/cypress/support/commands.ts b/e2e/freight/cypress/support/commands.ts new file mode 100644 index 000000000..9fc1b83ee --- /dev/null +++ b/e2e/freight/cypress/support/commands.ts @@ -0,0 +1,95 @@ +/** + * Auth model (see apps/edr-freight-api + freight web apps): + * - POST {api}/api/auth/login { email, password } + * → flattened body { success, token, refreshToken } (response interceptor + * flattens /api/auth responses — no .data nesting). + * - Both web apps read cookies `auth-token` / `refresh-token` and attach + * `Authorization: Bearer `. + * - Cookies are port-agnostic on localhost, so portal and backoffice share + * one cookie jar. cy.session snapshots/restores cookies per session id, + * which keeps staff and customer sessions from clobbering each other — + * but inside a single test, switching apps requires re-invoking the + * matching login command first (see flows specs). + */ + +export interface LoginBody { + success: boolean; + token: string; + refreshToken: string; +} + +const apiUrl = () => Cypress.env("apiUrl") as string; +const password = () => Cypress.env("defaultPassword") as string; + +function apiLogin(email: string, pass?: string): Cypress.Chainable { + return cy + .request("POST", `${apiUrl()}/api/auth/login`, { + email, + password: pass ?? password(), + }) + .then((response) => { + expect(response.status).to.eq(201); + expect(response.body.token, "login token").to.be.a("string"); + return cy.wrap(response.body, { log: false }); + }); +} + +function sessionFor(app: "backoffice" | "portal", email: string, pass?: string) { + cy.session( + [app, email], + () => { + apiLogin(email, pass).then(({ token, refreshToken }) => { + cy.setCookie("auth-token", token); + cy.setCookie("refresh-token", refreshToken); + }); + }, + { + cacheAcrossSpecs: true, + validate() { + cy.getCookie("auth-token").then((cookie) => { + expect(cookie, "auth-token cookie").to.exist; + cy.request({ + url: `${apiUrl()}/api/me`, + headers: { Authorization: `Bearer ${cookie!.value}` }, + }) + .its("status") + .should("eq", 200); + }); + }, + }, + ); +} + +Cypress.Commands.add("apiLogin", (email: string, pass?: string) => apiLogin(email, pass)); + +Cypress.Commands.add("loginBackoffice", (email = "ceo@edr.local", pass?: string) => { + sessionFor("backoffice", email, pass); +}); + +Cypress.Commands.add("loginPortal", (email = "user@gmail.com", pass?: string) => { + // Demo portal users are seeded with a hardcoded password (DemoUsersSeeder), + // unlike staff users which use DEFAULT_PASSWORD. + sessionFor("portal", email, pass ?? (Cypress.env("demoPassword") as string)); +}); + +Cypress.Commands.add("visitPortal", (path = "/") => { + cy.visit(`${Cypress.env("portalUrl")}${path}`); +}); + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Cypress { + interface Chainable { + /** POST /api/auth/login, returns the flattened token body. */ + apiLogin(email: string, pass?: string): Chainable; + /** Cached programmatic staff session (default ceo@edr.local). */ + loginBackoffice(email?: string, pass?: string): Chainable; + /** Cached programmatic customer session (default user@gmail.com). */ + loginPortal(email?: string, pass?: string): Chainable; + /** cy.visit against the portal origin (env.portalUrl). */ + visitPortal(path?: string): Chainable; + } + } +} + +export {}; diff --git a/e2e/freight/cypress/support/e2e.ts b/e2e/freight/cypress/support/e2e.ts new file mode 100644 index 000000000..49bc8540b --- /dev/null +++ b/e2e/freight/cypress/support/e2e.ts @@ -0,0 +1,18 @@ +import "./commands"; + +// The API's user seeders are disabled in app code — the SQL fixture creates +// the staff + demo test users instead. Idempotent, runs before each spec file. +before(() => { + cy.task("db:seedUsers"); +}); + +// Third-party noise (PostHog, Google Maps, socket.io reconnects) can throw +// uncaught exceptions that are irrelevant to the assertion under test. App +// errors still fail tests via failed assertions / failed intercepts. +Cypress.on("uncaught:exception", (err) => { + const ignorable = [/posthog/i, /google/i, /websocket/i, /socket\.io/i, /ResizeObserver/i]; + if (ignorable.some((pattern) => pattern.test(err.message))) { + return false; + } + return true; +}); diff --git a/e2e/freight/package.json b/e2e/freight/package.json new file mode 100644 index 000000000..4097b09da --- /dev/null +++ b/e2e/freight/package.json @@ -0,0 +1,22 @@ +{ + "name": "@edr/freight-e2e", + "version": "0.0.0", + "private": true, + "description": "Cypress end-to-end tests for the EDR freight system (portal + backoffice + API)", + "scripts": { + "cy:open": "cypress open --e2e", + "cy:run": "cypress run", + "cy:run:backoffice": "cypress run --spec 'cypress/e2e/backoffice/**'", + "cy:run:portal": "cypress run --spec 'cypress/e2e/portal/**'", + "cy:run:api": "cypress run --spec 'cypress/e2e/api/**'", + "cy:run:flows": "cypress run --spec 'cypress/e2e/flows/**'", + "type-check": "tsc --noEmit" + }, + "devDependencies": { + "cypress": "^15.3.0", + "pg": "^8.13.0", + "typescript": "^5.5.4", + "@types/node": "^22.0.0", + "@types/pg": "^8.11.0" + } +} diff --git a/e2e/freight/tsconfig.json b/e2e/freight/tsconfig.json new file mode 100644 index 000000000..c2b049986 --- /dev/null +++ b/e2e/freight/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "skipLibCheck": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "types": ["cypress", "node"] + }, + "include": ["cypress/**/*.ts", "cypress.config.ts"] +} diff --git a/package.json b/package.json index 8909de6cf..d01da8714 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,11 @@ "format": "prettier --write \"**/*.{ts,tsx,json,md}\"", "docker:build": "docker compose build", "docker:up": "docker compose up -d", + "e2e:freight:up": "docker compose -f docker-compose.e2e.yaml up -d --build --wait", + "e2e:freight:open": "pnpm --filter @edr/freight-e2e cy:open", + "e2e:freight:run": "pnpm --filter @edr/freight-e2e cy:run", + "e2e:freight:ci": "docker compose -f docker-compose.e2e.yaml --profile cypress run --rm cypress", + "e2e:freight:down": "docker compose -f docker-compose.e2e.yaml down -v --remove-orphans", "prepare": "husky" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f59a388ba..72daf6a26 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -580,7 +580,7 @@ importers: version: 5.101.0(react@19.2.6) '@tria-plc/iamui': specifier: file:../../../local-packages/tria-plc-iamui-0.1.1.tgz - version: file:local-packages/tria-plc-iamui-0.1.1.tgz(0ce39b7e349029277dcd938d06eeb0f7) + version: file:local-packages/tria-plc-iamui-0.1.1.tgz(a5d0bdee55164ae56064fb273b530e00) '@vis.gl/react-google-maps': specifier: ^1.8.3 version: 1.8.3(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -1203,6 +1203,24 @@ importers: specifier: ^5.5.4 version: 5.9.3 + e2e/freight: + devDependencies: + '@types/node': + specifier: ^22.0.0 + version: 22.20.1 + '@types/pg': + specifier: ^8.11.0 + version: 8.20.0 + cypress: + specifier: ^15.3.0 + version: 15.18.1 + pg: + specifier: ^8.13.0 + version: 8.21.0 + typescript: + specifier: ^5.5.4 + version: 5.9.3 + packages/api-common: dependencies: '@edr/types': @@ -1743,6 +1761,13 @@ packages: resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} engines: {node: '>=18'} + '@cypress/request@4.0.1': + resolution: {integrity: sha512-y20e+e6dFYkOUUJLVUZTsJRuTiXZaUQ32WD+R/ux/HBybbTx4ge7cNINcua0pU8+SNkKuRbOF12mBmzuzM8n5w==} + engines: {node: '>= 14.17.0'} + + '@cypress/xvfb@1.2.4': + resolution: {integrity: sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==} + '@date-fns/tz@1.5.0': resolution: {integrity: sha512-lwYN/vDPeNRULcepoE/LO2Pgx+7/RV+S9ARfbc9lr2DtGkOD7pAiruHvbR1RX3Qyf6ja47EWJDMsNK5vK08DJg==} @@ -4702,6 +4727,9 @@ packages: '@types/node@20.19.42': resolution: {integrity: sha512-5L7SUaFC1RyDraj2yRhyBzHTobyXHmohD100CChNtyPyleoq37Mqab5Gn8XEKI04dfN/oqPdpHk38MgcQWHbZg==} + '@types/node@22.20.1': + resolution: {integrity: sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==} + '@types/node@24.13.1': resolution: {integrity: sha512-RSpUJGmvsJ1ZeBehQZFhIdpsz+bIpES0nIQXko4Ybq+N+kX6XvOq3Jo+iJ82FWLdblFq85AsMikd3m35jgezYg==} @@ -4760,6 +4788,9 @@ packages: '@types/signature_pad@2.3.6': resolution: {integrity: sha512-v3j92gCQJoxomHhd+yaG4Vsf8tRS/XbzWKqDv85UsqjMGy4zhokuwKe4b6vhbgncKkh+thF+gpz6+fypTtnFqQ==} + '@types/sinonjs__fake-timers@8.1.1': + resolution: {integrity: sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==} + '@types/sizzle@2.3.10': resolution: {integrity: sha512-TC0dmN0K8YcWEAEfiPi5gJP14eJe30TTGjkvek3iM/1NdHHsdCA/Td6GvNndMOo/iSnIsZ4HuuhrYPDAmbxzww==} @@ -4778,6 +4809,9 @@ packages: '@types/tinymce@4.6.9': resolution: {integrity: sha512-pDxBUlV4v1jgJ97SlnVOSyf3KUy3OQ3s5Ddpfh1L9M5lXlBmX7TJ2OLSozx1WBxp91acHvYPWDwz2U/kMM1oxQ==} + '@types/tmp@0.2.6': + resolution: {integrity: sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==} + '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -5372,6 +5406,9 @@ packages: append-field@1.0.0: resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} + arch@2.2.0: + resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + archiver-utils@2.1.0: resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} engines: {node: '>= 6'} @@ -5472,6 +5509,13 @@ packages: asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + asn1@0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + + assert-plus@1.0.0: + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} + assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -5504,6 +5548,10 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + atob@2.1.2: resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} engines: {node: '>= 4.5.0'} @@ -5527,6 +5575,12 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + aws-sign2@0.7.0: + resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} + + aws4@1.13.2: + resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} + axe-core@4.12.0: resolution: {integrity: sha512-FTavr/7Ba0IptwGOPxnQvdyW2tAsdLBMTBXz7rKH6xJ2skpyxpBxyHkDdBs4lf69yRqYpkqCdfhnwS8YULGOmg==} engines: {node: '>=4'} @@ -5663,6 +5717,9 @@ packages: resolution: {integrity: sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==} engines: {node: '>=10.0.0'} + bcrypt-pbkdf@1.0.2: + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + bcrypt@6.0.0: resolution: {integrity: sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==} engines: {node: '>= 18'} @@ -5684,12 +5741,18 @@ packages: bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + blob-util@2.0.2: + resolution: {integrity: sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==} + block-stream2@2.1.0: resolution: {integrity: sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==} bluebird@3.4.7: resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==} + bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + body-parser@1.20.5: resolution: {integrity: sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -5794,6 +5857,10 @@ packages: resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} engines: {node: '>=0.10.0'} + cachedir@2.4.0: + resolution: {integrity: sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==} + engines: {node: '>=6'} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -5832,6 +5899,9 @@ packages: resolution: {integrity: sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==} engines: {node: '>=10.0.0'} + caseless@0.12.0: + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + cfb@1.2.2: resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==} engines: {node: '>=0.8'} @@ -5890,6 +5960,10 @@ packages: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} + ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + engines: {node: '>=8'} + citty@0.1.6: resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} @@ -5931,6 +6005,10 @@ packages: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} + cli-table3@0.6.1: + resolution: {integrity: sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==} + engines: {node: 10.* || >= 12.*} + cli-table3@0.6.5: resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} engines: {node: 10.* || >= 12.*} @@ -5939,6 +6017,10 @@ packages: resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} engines: {node: '>=18'} + cli-truncate@5.2.0: + resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} + engines: {node: '>=20'} + cli-width@1.1.1: resolution: {integrity: sha512-eMU2akIeEIkCxGXUNmDnJq1KzOIiPnJ+rKqRe6hcxE3vIOPvpMrBYOn/Bl7zNlYJj/zQxXquAnozHUCf9Whnsg==} @@ -6022,6 +6104,10 @@ packages: resolution: {integrity: sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==} engines: {node: '>=0.1.90'} + colors@1.4.0: + resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} + engines: {node: '>=0.1.90'} + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -6045,10 +6131,18 @@ packages: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} + commander@6.2.1: + resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} + engines: {node: '>= 6'} + comment-json@5.0.0: resolution: {integrity: sha512-uiqLcOiVDJtBP8WGkZHEP+FZIhTzP1dxvn59EfoYUi9gqupjrBWVQkO2atDrbnKPwLeotFYDsuNb26uBMqB+hw==} engines: {node: '>= 6'} + common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + compare-func@2.0.0: resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} @@ -6140,6 +6234,9 @@ packages: core-js@3.49.0: resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==} + core-util-is@1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -6254,6 +6351,11 @@ packages: resolution: {integrity: sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==} engines: {node: '>=0.4.0'} + cypress@15.18.1: + resolution: {integrity: sha512-JtkTVtUE2lvLYgZCaug+Uai0H9IqsJirlBO49c87QwG0bJUGvAUVBz1EJve0b0oaYP244Ew9M0BkrHpcqkYxmw==} + engines: {node: ^20.1.0 || ^22.0.0 || >=24.0.0} + hasBin: true + d3-array@3.2.4: resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} engines: {node: '>=12'} @@ -6305,6 +6407,10 @@ packages: resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} engines: {node: '>=12'} + dashdash@1.14.1: + resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} + engines: {node: '>=0.10'} + data-uri-to-buffer@4.0.1: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} engines: {node: '>= 12'} @@ -6587,6 +6693,9 @@ packages: ebec@2.3.0: resolution: {integrity: sha512-bt+0tSL7223VU3PSVi0vtNLZ8pO1AfWolcPPMk2a/a5H+o/ZU9ky0n3A0zhrR4qzJTN61uPsGIO4ShhOukdzxA==} + ecc-jsbn@0.1.2: + resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} + ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} @@ -6913,6 +7022,9 @@ packages: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} + eventemitter2@6.4.7: + resolution: {integrity: sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==} + eventemitter2@6.4.9: resolution: {integrity: sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==} @@ -6941,6 +7053,10 @@ packages: resolution: {integrity: sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg==} engines: {node: '>=8.3.0'} + execa@4.1.0: + resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} + engines: {node: '>=10'} + execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -6953,6 +7069,10 @@ packages: resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==} engines: {node: ^18.19.0 || >=20.5.0} + executable@4.1.1: + resolution: {integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==} + engines: {node: '>=4'} + exit-hook@1.1.1: resolution: {integrity: sha512-MsG3prOVw1WtLXAZbM3KiYtooKR1LvxHh3VHsVtIy0uiUu8usxgB/94DP2HxtD/661lLdB6yzQ09lGJSQr6nkg==} engines: {node: '>=0.10.0'} @@ -6998,6 +7118,9 @@ packages: resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} engines: {node: '>=0.10.0'} + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + extglob@2.0.4: resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} engines: {node: '>=0.10.0'} @@ -7007,6 +7130,10 @@ packages: engines: {node: '>= 10.17.0'} hasBin: true + extsprintf@1.3.0: + resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} + engines: {'0': node >=0.6.0} + eyes@0.1.8: resolution: {integrity: sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==} engines: {node: '> 0.1.90'} @@ -7191,6 +7318,9 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} + forever-agent@0.6.1: + resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} + fork-ts-checker-webpack-plugin@9.1.0: resolution: {integrity: sha512-mpafl89VFPJmhnJ1ssH+8wmM2b50n+Rew5x42NeI2U78aRWgtkEtGmctp7iT16UjquJTjorEmIfESj3DxdW84Q==} engines: {node: '>=14.21.3'} @@ -7262,6 +7392,10 @@ packages: resolution: {integrity: sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==} engines: {node: '>=14.14'} + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + fs-monkey@1.1.0: resolution: {integrity: sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==} @@ -7362,6 +7496,9 @@ packages: resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} engines: {node: '>=0.10.0'} + getpass@0.1.7: + resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} + giget@2.0.0: resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==} hasBin: true @@ -7406,6 +7543,10 @@ packages: resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} engines: {node: '>=18'} + global-dirs@3.0.1: + resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} + engines: {node: '>=10'} + globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} @@ -7501,6 +7642,10 @@ packages: resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} engines: {node: '>=0.10.0'} + hasha@5.2.2: + resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==} + engines: {node: '>=8'} + hasown@2.0.4: resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} @@ -7571,6 +7716,10 @@ packages: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} + http-signature@1.4.0: + resolution: {integrity: sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==} + engines: {node: '>=0.10'} + https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -7579,6 +7728,10 @@ packages: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} + human-signals@1.1.1: + resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} + engines: {node: '>=8.12.0'} + human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -7684,6 +7837,10 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + ini@2.0.0: + resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} + engines: {node: '>=10'} + ini@4.1.1: resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -7852,6 +8009,10 @@ packages: engines: {node: '>=14.16'} hasBin: true + is-installed-globally@0.4.0: + resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} + engines: {node: '>=10'} + is-interactive@1.0.0: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} @@ -7969,6 +8130,9 @@ packages: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} + is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} @@ -8257,6 +8421,9 @@ packages: resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==} hasBin: true + jsbn@0.1.1: + resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} + jsdom@25.0.1: resolution: {integrity: sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==} engines: {node: '>=18'} @@ -8286,12 +8453,18 @@ packages: json-schema-typed@8.0.2: resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} json-stream@1.0.0: resolution: {integrity: sha512-H/ZGY0nIAg3QcOwE1QN/rK/Fa7gJn7Ii5obwp6zyPO4xiPNwpIMjqy2gwjBEGqzkF/vSWEIBQCBuN19hYiL6Qg==} + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + json5@1.0.2: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true @@ -8330,6 +8503,10 @@ packages: jspdf@4.2.1: resolution: {integrity: sha512-YyAXyvnmjTbR4bHQRLzex3CuINCDlQnBqoSYyjJwTP2x9jDLuKDzy7aKUl0hgx3uhcl7xzg32agn5vlie6HIlQ==} + jsprim@2.0.2: + resolution: {integrity: sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==} + engines: {'0': node >=0.6.0} + jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -8508,6 +8685,10 @@ packages: resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==} engines: {node: '>=18.0.0'} + listr2@9.0.5: + resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==} + engines: {node: '>=20.0.0'} + little-state-machine@4.8.1: resolution: {integrity: sha512-liPHqaWMQ7rzZryQUDnbZ1Gclnnai3dIyaJ0nAgwZRXMzqbYrydrlCI0NDojRUbE5VYh5vu6hygEUZiH77nQkQ==} peerDependencies: @@ -9194,6 +9375,9 @@ packages: resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} engines: {node: '>=18'} + ospath@1.2.2: + resolution: {integrity: sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==} + outvariant@1.4.3: resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} @@ -9562,6 +9746,10 @@ packages: engines: {node: '>=14'} hasBin: true + pretty-bytes@5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -9609,6 +9797,9 @@ packages: resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} engines: {node: '>= 14'} + proxy-from-env@1.0.0: + resolution: {integrity: sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==} + proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -10083,6 +10274,9 @@ packages: resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} engines: {node: '>=0.10'} + request-progress@3.0.0: + resolution: {integrity: sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==} + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -10410,6 +10604,10 @@ packages: resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} engines: {node: '>=18'} + slice-ansi@8.0.0: + resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} + engines: {node: '>=20'} + smart-buffer@4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} @@ -10516,6 +10714,11 @@ packages: resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==} engines: {node: '>=0.8'} + sshpk@1.18.0: + resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} + engines: {node: '>=0.10.0'} + hasBin: true + stable-hash@0.0.5: resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} @@ -10593,6 +10796,10 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} + string-width@8.2.2: + resolution: {integrity: sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==} + engines: {node: '>=20'} + string.prototype.includes@2.0.1: resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} engines: {node: '>= 0.4'} @@ -10766,6 +10973,12 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + systeminformation@5.33.0: + resolution: {integrity: sha512-0LYSL01CCbjVeJG7iXI8fUCFU76zMjzbHd/EU3or4QpSFYCLMgslR11prwHuA3siz5jmOkqoLhjgOyDRmXBKmA==} + engines: {node: '>=10.0.0'} + os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android] + hasBin: true + tabbable@6.4.0: resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==} @@ -10883,6 +11096,9 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + throttleit@1.0.1: + resolution: {integrity: sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==} + through2@2.0.5: resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} @@ -11006,6 +11222,10 @@ packages: traverse@0.3.9: resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==} + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + trim-canvas@0.1.2: resolution: {integrity: sha512-nd4Ga3iLFV94mdhW9JFMLpQbHUyCQuhFOD71PEAt1NjtMD5wbZctzhX8c3agHNybMR5zXD1XTGoIEWk995E6pQ==} @@ -11090,6 +11310,9 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + turbo@2.9.16: resolution: {integrity: sha512-NqgRQy6j6dPYcdSdv0q1g9QsZg7SWg87RERM8otw/1AtKU2yTFVClOM7cbwKzOonZr/Ek1blTBucw64L9H0Bwg==} hasBin: true @@ -11097,6 +11320,9 @@ packages: tw-animate-css@1.4.0: resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} + tweetnacl@0.14.5: + resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -11113,6 +11339,10 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + type-fest@4.41.0: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} @@ -11285,6 +11515,10 @@ packages: until-async@3.0.2: resolution: {integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==} + untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + unzipper@0.10.14: resolution: {integrity: sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==} @@ -11425,6 +11659,10 @@ packages: react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc + verror@1.10.0: + resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} + engines: {'0': node >=0.6.0} + victory-vendor@36.9.2: resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==} @@ -11763,6 +12001,10 @@ packages: yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + yauzl@3.4.0: + resolution: {integrity: sha512-jIH9yLR9wqr0wOS0TpBvo/g/2UgZH5qePVbjgRliiF0BYvOZyaBknKsF+x9Iht0O6sqgnB93rCICdOZFecJuDw==} + engines: {node: '>=12'} + year@0.2.1: resolution: {integrity: sha512-9GnJUZ0QM4OgXuOzsKNzTJ5EOkums1Xc+3YQXp+Q+UxFjf7zLucp9dQ8QMIft0Szs1E1hUiXFim1OYfEKFq97w==} engines: {node: '>=0.8'} @@ -11889,11 +12131,11 @@ snapshots: '@babel/helpers': 7.29.7 '@babel/parser': 7.29.7 '@babel/template': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@5.5.0) + '@babel/traverse': 7.29.7 '@babel/types': 7.29.7 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -11928,7 +12170,7 @@ snapshots: '@babel/helper-optimise-call-expression': 7.29.7 '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7) '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@5.5.0) + '@babel/traverse': 7.29.7 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -11937,7 +12179,14 @@ snapshots: '@babel/helper-member-expression-to-functions@7.29.7': dependencies: - '@babel/traverse': 7.29.7(supports-color@5.5.0) + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.29.7': + dependencies: + '@babel/traverse': 7.29.7 '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color @@ -11952,9 +12201,9 @@ snapshots: '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 - '@babel/helper-module-imports': 7.29.7(supports-color@5.5.0) + '@babel/helper-module-imports': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@5.5.0) + '@babel/traverse': 7.29.7 transitivePeerDependencies: - supports-color @@ -11969,13 +12218,13 @@ snapshots: '@babel/core': 7.29.7 '@babel/helper-member-expression-to-functions': 7.29.7 '@babel/helper-optimise-call-expression': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@5.5.0) + '@babel/traverse': 7.29.7 transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.29.7': dependencies: - '@babel/traverse': 7.29.7(supports-color@5.5.0) + '@babel/traverse': 7.29.7 '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color @@ -12128,6 +12377,18 @@ snapshots: '@babel/parser': 7.29.7 '@babel/types': 7.29.7 + '@babel/traverse@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + '@babel/traverse@7.29.7(supports-color@5.5.0)': dependencies: '@babel/code-frame': 7.29.7 @@ -12286,6 +12547,33 @@ snapshots: '@csstools/css-tokenizer@3.0.4': {} + '@cypress/request@4.0.1': + dependencies: + aws-sign2: 0.7.0 + aws4: 1.13.2 + caseless: 0.12.0 + combined-stream: 1.0.8 + extend: 3.0.2 + forever-agent: 0.6.1 + form-data: 4.0.5 + http-signature: 1.4.0 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.35 + performance-now: 2.1.0 + qs: 6.15.2 + safe-buffer: 5.2.1 + tough-cookie: 5.1.2 + tunnel-agent: 0.6.0 + + '@cypress/xvfb@1.2.4(supports-color@8.1.1)': + dependencies: + debug: 3.2.7(supports-color@8.1.1) + lodash.once: 4.1.1 + transitivePeerDependencies: + - supports-color + '@date-fns/tz@1.5.0': {} '@dotenvx/dotenvx@1.71.0': @@ -12324,7 +12612,7 @@ snapshots: '@emotion/babel-plugin@11.13.5': dependencies: - '@babel/helper-module-imports': 7.29.7(supports-color@5.5.0) + '@babel/helper-module-imports': 7.29.7 '@babel/runtime': 7.29.7 '@emotion/hash': 0.9.2 '@emotion/memoize': 0.9.0 @@ -12490,7 +12778,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.15.0 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) espree: 9.6.1 globals: 13.24.0 ignore: 5.3.2 @@ -12636,7 +12924,7 @@ snapshots: '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) minimatch: 3.1.5 transitivePeerDependencies: - supports-color @@ -13803,7 +14091,7 @@ snapshots: '@puppeteer/browsers@2.13.2': dependencies: - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) extract-zip: 2.0.1 progress: 2.0.3 proxy-agent: 6.5.0 @@ -15871,7 +16159,7 @@ snapshots: '@tokenizer/inflate@0.4.1': dependencies: - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) token-types: 6.1.2 transitivePeerDependencies: - supports-color @@ -16162,6 +16450,130 @@ snapshots: - utf-8-validate - vite + '@tria-plc/iamui@file:local-packages/tria-plc-iamui-0.1.1.tgz(a5d0bdee55164ae56064fb273b530e00)': + dependencies: + '@emotion/react': 11.14.0(@types/react@18.3.31)(react@19.2.6) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6) + '@hookform/resolvers': 5.4.0(react-hook-form@7.77.0(react@19.2.6)) + '@lottiefiles/react-lottie-player': 3.6.0(react@19.2.6) + '@mantine/charts': 7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/hooks@7.17.8(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(recharts@3.8.1(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react-is@19.2.7)(react@19.2.6)(redux@5.0.1)) + '@mantine/core': 7.17.8(@mantine/hooks@7.17.8(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@mantine/dates': 7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/hooks@7.17.8(react@19.2.6))(dayjs@1.11.21)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@mantine/hooks': 7.17.8(react@19.2.6) + '@mantine/notifications': 7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/hooks@7.17.8(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-accordion': 1.2.13(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-alert-dialog': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-avatar': 1.1.12(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-checkbox': 1.3.4(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-collapsible': 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-context-menu': 2.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-dialog': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-dropdown-menu': 2.1.17(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-hover-card': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-label': 2.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-navigation-menu': 1.2.15(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-popover': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-progress': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-radio-group': 1.4.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-scroll-area': 1.2.11(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-select': 2.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-separator': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-slot': 1.2.5(@types/react@18.3.31)(react@19.2.6) + '@radix-ui/react-switch': 1.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-tabs': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-toast': 1.2.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-tooltip': 1.2.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@react-pdf-viewer/default-layout': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@react-pdf/renderer': 4.5.1(react@19.2.6) + '@reduxjs/toolkit': 2.12.0(react-redux@9.3.0(@types/react@18.3.31)(react@19.2.6)(redux@5.0.1))(react@19.2.6) + '@tabler/icons-react': 3.44.0(react@19.2.6) + '@tailwindcss/vite': 4.3.0(vite@5.4.21(@types/node@24.13.1)(lightningcss@1.32.0)(terser@5.48.0)) + '@tanstack/react-query': 5.101.0(react@19.2.6) + '@tanstack/react-query-devtools': 5.101.0(@tanstack/react-query@5.101.0(react@19.2.6))(react@19.2.6) + '@tanstack/react-table': 8.21.3(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@tinymce/tinymce-react': 6.3.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(tinymce@7.9.3) + '@types/dompurify': 3.2.0 + '@types/node': 24.13.1 + '@types/tinymce': 4.6.9 + axios: 1.17.0 + class-variance-authority: 0.7.1 + clsx: 2.1.1 + cmdk: 1.1.1(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + date-fns: 3.6.0 + dayjs: 1.11.21 + dompurify: 3.4.8 + ethiopian-calendar-date-converter: 2.1.6 + ethiopian-calendar-new: 1.1.0 + file-type: 18.7.0 + framer-motion: 12.40.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + html2canvas: 1.4.1 + i18next: 25.10.10(typescript@5.9.3) + i18next-browser-languagedetector: 8.2.1 + jquery: 3.7.1 + js-cookie: 3.0.8 + jspdf: 3.0.4 + lodash: 4.18.1 + lucide-react: 0.513.0(react@19.2.6) + mantine-react-table: 2.0.0-beta.9(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/dates@7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/hooks@7.17.8(react@19.2.6))(dayjs@1.11.21)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/hooks@7.17.8(react@19.2.6))(@tabler/icons-react@3.44.0(react@19.2.6))(clsx@2.1.1)(dayjs@1.11.21)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + mui-ethiopian-datepicker: 0.3.2(4b3af212eafdf0059f009b005d7e343d) + next-themes: 0.4.6(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + path: 0.12.7 + pdf-lib: 1.17.1 + qs: 6.15.2 + react: 19.2.6 + react-cookie: 8.1.2(@types/react@18.3.31)(react@19.2.6) + react-css-nocode-editor: 1.0.13(react-dom@19.2.6(react@19.2.6))(react-is@19.2.7)(react@19.2.6) + react-day-picker: 8.10.2(date-fns@3.6.0)(react@19.2.6) + react-dom: 19.2.6(react@19.2.6) + react-dropzone: 14.4.1(react@19.2.6) + react-hook-form: 7.77.0(react@19.2.6) + react-i18next: 15.7.4(i18next@25.10.10(typescript@5.9.3))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(typescript@5.9.3) + react-icons: 5.6.0(react@19.2.6) + react-image-crop: 11.0.10(react@19.2.6) + react-intersection-observer: 9.16.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + react-pdf: 10.4.1(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + react-pdf-html: 2.1.5(@react-pdf/renderer@4.5.1(react@19.2.6))(react@19.2.6) + react-redux: 9.3.0(@types/react@18.3.31)(react@19.2.6)(redux@5.0.1) + react-resizable-panels: 3.0.6(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + react-router-dom: 7.17.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + react-signature-canvas: 1.1.0-alpha.2(@types/prop-types@15.7.15)(@types/react@18.3.31)(prop-types@15.8.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + recharts: 3.8.1(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react-is@19.2.7)(react@19.2.6)(redux@5.0.1) + rollup-plugin-visualizer: 7.0.1(rollup@4.61.1) + socket.io-client: 4.8.3 + sonner: 2.0.7(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + tailwind-merge: 3.6.0 + tailwind-scrollbar-hide: 4.0.0(tailwindcss@4.3.0) + tailwindcss: 4.3.0 + tailwindcss-animate: 1.0.7(tailwindcss@4.3.0) + tinymce: 7.9.3 + url: 0.11.4 + vaul: 1.1.2(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + xlsx: 0.18.5 + zod: 3.25.76 + transitivePeerDependencies: + - '@babel/core' + - '@emotion/is-prop-valid' + - '@mui/icons-material' + - '@mui/material' + - '@mui/x-date-pickers' + - '@types/prop-types' + - '@types/react' + - '@types/react-dom' + - bufferutil + - debug + - pdfjs-dist + - prop-types + - react-is + - react-native + - redux + - rolldown + - rollup + - supports-color + - typescript + - utf-8-validate + - vite + '@ts-morph/common@0.27.0': dependencies: fast-glob: 3.3.3 @@ -16376,6 +16788,10 @@ snapshots: dependencies: undici-types: 6.21.0 + '@types/node@22.20.1': + dependencies: + undici-types: 6.21.0 + '@types/node@24.13.1': dependencies: undici-types: 7.18.2 @@ -16442,6 +16858,8 @@ snapshots: '@types/signature_pad@2.3.6': {} + '@types/sinonjs__fake-timers@8.1.1': {} + '@types/sizzle@2.3.10': {} '@types/stack-utils@2.0.3': {} @@ -16464,6 +16882,8 @@ snapshots: dependencies: '@types/jquery': 4.0.1 + '@types/tmp@0.2.6': {} + '@types/trusted-types@2.0.7': optional: true @@ -16514,7 +16934,7 @@ snapshots: '@typescript-eslint/types': 8.60.1 '@typescript-eslint/typescript-estree': 8.60.1(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.60.1 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) eslint: 8.57.1 typescript: 5.9.3 transitivePeerDependencies: @@ -16524,7 +16944,7 @@ snapshots: dependencies: '@typescript-eslint/tsconfig-utils': 8.60.1(typescript@5.9.3) '@typescript-eslint/types': 8.60.1 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -16543,7 +16963,7 @@ snapshots: '@typescript-eslint/types': 8.60.1 '@typescript-eslint/typescript-estree': 8.60.1(typescript@5.9.3) '@typescript-eslint/utils': 8.60.1(eslint@8.57.1)(typescript@5.9.3) - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) eslint: 8.57.1 ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 @@ -16558,7 +16978,7 @@ snapshots: '@typescript-eslint/tsconfig-utils': 8.60.1(typescript@5.9.3) '@typescript-eslint/types': 8.60.1 '@typescript-eslint/visitor-keys': 8.60.1 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) minimatch: 10.2.5 semver: 7.8.2 tinyglobby: 0.2.17 @@ -16838,7 +17258,7 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -17093,6 +17513,8 @@ snapshots: append-field@1.0.0: {} + arch@2.2.0: {} + archiver-utils@2.1.0: dependencies: glob: 7.2.3 @@ -17240,6 +17662,12 @@ snapshots: asap@2.0.6: {} + asn1@0.2.6: + dependencies: + safer-buffer: 2.1.2 + + assert-plus@1.0.0: {} + assertion-error@2.0.1: {} assign-symbols@1.0.0: {} @@ -17264,6 +17692,8 @@ snapshots: asynckit@0.4.0: {} + at-least-node@1.0.0: {} + atob@2.1.2: {} attr-accept@2.2.5: {} @@ -17285,6 +17715,10 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 + aws-sign2@0.7.0: {} + + aws4@1.13.2: {} + axe-core@4.12.0: {} axios@1.17.0: @@ -17348,6 +17782,16 @@ snapshots: transitivePeerDependencies: - supports-color + babel-plugin-styled-components@2.3.0(styled-components@5.3.11(react-dom@19.2.6(react@19.2.6))(react-is@19.2.7)(react@19.2.6))(supports-color@5.5.0): + dependencies: + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-module-imports': 7.29.7(supports-color@5.5.0) + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) + picomatch: 4.0.4 + styled-components: 5.3.11(react-dom@19.2.6(react@19.2.6))(react-is@19.2.7)(react@19.2.6) + transitivePeerDependencies: + - supports-color + babel-polyfill@6.26.0: dependencies: babel-runtime: 6.26.0 @@ -17442,6 +17886,10 @@ snapshots: basic-ftp@5.3.1: {} + bcrypt-pbkdf@1.0.2: + dependencies: + tweetnacl: 0.14.5 + bcrypt@6.0.0: dependencies: node-addon-api: 8.8.0 @@ -17466,12 +17914,16 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 + blob-util@2.0.2: {} + block-stream2@2.1.0: dependencies: readable-stream: 3.6.2 bluebird@3.4.7: {} + bluebird@3.7.2: {} + body-parser@1.20.5: dependencies: bytes: 3.1.2 @@ -17493,7 +17945,7 @@ snapshots: dependencies: bytes: 3.1.2 content-type: 1.0.5 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) http-errors: 2.0.1 iconv-lite: 0.7.2 on-finished: 2.4.1 @@ -17624,6 +18076,8 @@ snapshots: union-value: 1.0.1 unset-value: 1.0.0 + cachedir@2.4.0: {} + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -17665,6 +18119,8 @@ snapshots: svg-pathdata: 6.0.3 optional: true + caseless@0.12.0: {} + cfb@1.2.2: dependencies: adler-32: 1.3.1 @@ -17731,6 +18187,8 @@ snapshots: ci-info@3.9.0: {} + ci-info@4.4.0: {} + citty@0.1.6: dependencies: consola: 3.4.2 @@ -17774,6 +18232,12 @@ snapshots: cli-spinners@2.9.2: {} + cli-table3@0.6.1: + dependencies: + string-width: 4.2.3 + optionalDependencies: + colors: 1.4.0 + cli-table3@0.6.5: dependencies: string-width: 4.2.3 @@ -17785,6 +18249,11 @@ snapshots: slice-ansi: 5.0.0 string-width: 7.2.0 + cli-truncate@5.2.0: + dependencies: + slice-ansi: 8.0.0 + string-width: 8.2.2 + cli-width@1.1.1: {} cli-width@4.1.0: {} @@ -17858,6 +18327,9 @@ snapshots: colors@1.0.3: {} + colors@1.4.0: + optional: true + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -17872,11 +18344,15 @@ snapshots: commander@4.1.1: {} + commander@6.2.1: {} + comment-json@5.0.0: dependencies: array-timsort: 1.0.3 esprima: 4.0.1 + common-tags@1.8.2: {} + compare-func@2.0.0: dependencies: array-ify: 1.0.0 @@ -17953,6 +18429,8 @@ snapshots: core-js@3.49.0: {} + core-util-is@1.0.2: {} + core-util-is@1.0.3: {} cors@2.8.6: @@ -18084,6 +18562,48 @@ snapshots: cycle@1.0.3: {} + cypress@15.18.1: + dependencies: + '@cypress/request': 4.0.1 + '@cypress/xvfb': 1.2.4(supports-color@8.1.1) + '@types/sinonjs__fake-timers': 8.1.1 + '@types/sizzle': 2.3.10 + '@types/tmp': 0.2.6 + arch: 2.2.0 + blob-util: 2.0.2 + bluebird: 3.7.2 + buffer: 5.7.1 + cachedir: 2.4.0 + chalk: 4.1.2 + ci-info: 4.4.0 + cli-table3: 0.6.1 + commander: 6.2.1 + common-tags: 1.8.2 + dayjs: 1.11.21 + debug: 4.4.3(supports-color@8.1.1) + eventemitter2: 6.4.7 + execa: 4.1.0 + executable: 4.1.1 + fs-extra: 9.1.0 + hasha: 5.2.2 + is-installed-globally: 0.4.0 + listr2: 9.0.5 + lodash: 4.18.1 + log-symbols: 4.1.0 + 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 + supports-color: 8.1.1 + systeminformation: 5.33.0 + tmp: 0.2.7 + tree-kill: 1.2.2 + tslib: 1.14.1 + untildify: 4.0.0 + yauzl: 3.4.0 + d3-array@3.2.4: dependencies: internmap: 2.0.3 @@ -18126,6 +18646,10 @@ snapshots: dargs@8.1.0: {} + dashdash@1.14.1: + dependencies: + assert-plus: 1.0.0 + data-uri-to-buffer@4.0.1: {} data-uri-to-buffer@6.0.2: {} @@ -18175,9 +18699,11 @@ snapshots: dependencies: ms: 2.0.0 - debug@3.2.7: + debug@3.2.7(supports-color@8.1.1): dependencies: ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 debug@4.4.3(supports-color@5.5.0): dependencies: @@ -18185,6 +18711,12 @@ snapshots: optionalDependencies: supports-color: 5.5.0 + debug@4.4.3(supports-color@8.1.1): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 + decamelize@1.2.0: {} decimal.js-light@2.5.1: {} @@ -18366,6 +18898,11 @@ snapshots: ebec@2.3.0: {} + ecc-jsbn@0.1.2: + dependencies: + jsbn: 0.1.1 + safer-buffer: 2.1.2 + ecdsa-sig-formatter@1.0.11: dependencies: safe-buffer: 5.2.1 @@ -18407,7 +18944,7 @@ snapshots: engine.io-client@6.6.5: dependencies: '@socket.io/component-emitter': 3.1.2 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) engine.io-parser: 5.2.3 ws: 8.20.1 xmlhttprequest-ssl: 2.1.2 @@ -18427,7 +18964,7 @@ snapshots: base64id: 2.0.0 cookie: 0.7.2 cors: 2.8.6 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) engine.io-parser: 5.2.3 ws: 8.21.0 transitivePeerDependencies: @@ -18651,7 +19188,7 @@ snapshots: eslint-import-resolver-node@0.3.10: dependencies: - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) is-core-module: 2.16.2 resolve: 2.0.0-next.7 transitivePeerDependencies: @@ -18660,7 +19197,7 @@ snapshots: eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.1(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1): dependencies: '@nolyfill/is-core-module': 1.0.39 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) eslint: 8.57.1 get-tsconfig: 4.14.0 is-bun-module: 2.0.0 @@ -18674,7 +19211,7 @@ snapshots: eslint-module-utils@2.13.0(@typescript-eslint/parser@8.60.1(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.1(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): dependencies: - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) optionalDependencies: '@typescript-eslint/parser': 8.60.1(eslint@8.57.1)(typescript@5.9.3) eslint: 8.57.1 @@ -18690,7 +19227,7 @@ snapshots: array.prototype.findlastindex: 1.2.6 array.prototype.flat: 1.3.3 array.prototype.flatmap: 1.3.3 - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.10 @@ -18788,7 +19325,7 @@ snapshots: ajv: 6.15.0 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -18854,6 +19391,8 @@ snapshots: event-target-shim@5.0.1: {} + eventemitter2@6.4.7: {} + eventemitter2@6.4.9: {} eventemitter3@4.0.7: {} @@ -18886,6 +19425,18 @@ snapshots: unzipper: 0.10.14 uuid: 8.3.2 + execa@4.1.0: + dependencies: + cross-spawn: 7.0.6 + get-stream: 5.2.0 + human-signals: 1.1.1 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -18925,6 +19476,10 @@ snapshots: strip-final-newline: 4.0.0 yoctocolors: 2.1.2 + executable@4.1.1: + dependencies: + pify: 2.3.0 + exit-hook@1.1.1: {} exit@0.1.2: {} @@ -19000,7 +19555,7 @@ snapshots: content-type: 1.0.5 cookie: 0.7.2 cookie-signature: 1.2.2 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) depd: 2.0.0 encodeurl: 2.0.0 escape-html: 1.0.3 @@ -19036,6 +19591,8 @@ snapshots: assign-symbols: 1.0.0 is-extendable: 1.0.1 + extend@3.0.2: {} + extglob@2.0.4: dependencies: array-unique: 0.3.2 @@ -19051,7 +19608,7 @@ snapshots: extract-zip@2.0.1: dependencies: - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -19059,6 +19616,8 @@ snapshots: transitivePeerDependencies: - supports-color + extsprintf@1.3.0: {} + eyes@0.1.8: {} falsey@0.3.2: @@ -19200,7 +19759,7 @@ snapshots: finalhandler@2.1.1: dependencies: - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 @@ -19266,6 +19825,8 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + forever-agent@0.6.1: {} + fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.106.0): dependencies: '@babel/code-frame': 7.29.7 @@ -19341,6 +19902,13 @@ snapshots: jsonfile: 6.2.1 universalify: 2.0.1 + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + fs-monkey@1.1.0: {} fs.realpath@1.0.0: {} @@ -19434,12 +20002,16 @@ snapshots: dependencies: basic-ftp: 5.3.1 data-uri-to-buffer: 6.0.2 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color get-value@2.0.6: {} + getpass@0.1.7: + dependencies: + assert-plus: 1.0.0 + giget@2.0.0: dependencies: citty: 0.1.6 @@ -19501,6 +20073,10 @@ snapshots: dependencies: ini: 4.1.1 + global-dirs@3.0.1: + dependencies: + ini: 2.0.0 + globals@13.24.0: dependencies: type-fest: 0.20.2 @@ -19623,6 +20199,11 @@ snapshots: is-number: 3.0.0 kind-of: 4.0.0 + hasha@5.2.2: + dependencies: + is-stream: 2.0.1 + type-fest: 0.8.1 + hasown@2.0.4: dependencies: function-bind: 1.1.2 @@ -19702,24 +20283,32 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.4 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color + http-signature@1.4.0: + dependencies: + assert-plus: 1.0.0 + jsprim: 2.0.2 + sshpk: 1.18.0 + https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.4 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color + human-signals@1.1.1: {} + human-signals@2.1.0: {} human-signals@5.0.0: {} @@ -19795,6 +20384,8 @@ snapshots: inherits@2.0.4: {} + ini@2.0.0: {} + ini@4.1.1: {} input-format@0.3.14(react-dom@19.2.6(react@19.2.6))(react@19.2.6): @@ -19960,6 +20551,11 @@ snapshots: dependencies: is-docker: 3.0.0 + is-installed-globally@0.4.0: + dependencies: + global-dirs: 3.0.1 + is-path-inside: 3.0.3 + is-interactive@1.0.0: {} is-interactive@2.0.0: {} @@ -20051,6 +20647,8 @@ snapshots: dependencies: which-typed-array: 1.1.22 + is-typedarray@1.0.0: {} + is-unicode-supported@0.1.0: {} is-unicode-supported@1.3.0: {} @@ -20124,7 +20722,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -20514,6 +21112,8 @@ snapshots: dependencies: argparse: 2.0.1 + jsbn@0.1.1: {} + jsdom@25.0.1: dependencies: cssstyle: 4.6.0 @@ -20554,10 +21154,14 @@ snapshots: json-schema-typed@8.0.2: {} + json-schema@0.4.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json-stream@1.0.0: {} + json-stringify-safe@5.0.1: {} + json5@1.0.2: dependencies: minimist: 1.2.8 @@ -20626,6 +21230,13 @@ snapshots: dompurify: 3.4.8 html2canvas: 1.4.1 + jsprim@2.0.2: + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 + jsx-ast-utils@3.3.5: dependencies: array-includes: 3.1.9 @@ -20778,7 +21389,7 @@ snapshots: dependencies: chalk: 5.6.2 commander: 13.1.0 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) execa: 8.0.1 lilconfig: 3.1.3 listr2: 8.3.3 @@ -20800,6 +21411,15 @@ snapshots: rfdc: 1.4.1 wrap-ansi: 9.0.2 + listr2@9.0.5: + dependencies: + cli-truncate: 5.2.0 + colorette: 2.0.20 + eventemitter3: 5.0.4 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.2 + little-state-machine@4.8.1(react@19.2.6): dependencies: react: 19.2.6 @@ -21493,6 +22113,8 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.2.0 + ospath@1.2.2: {} + outvariant@1.4.3: {} own-keys@1.0.1: @@ -21531,7 +22153,7 @@ snapshots: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.4 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) get-uri: 6.0.5 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 @@ -21658,8 +22280,7 @@ snapshots: perfect-debounce@1.0.0: {} - performance-now@2.1.0: - optional: true + performance-now@2.1.0: {} pg-cloudflare@1.4.0: optional: true @@ -21814,6 +22435,8 @@ snapshots: prettier@3.8.3: {} + pretty-bytes@5.6.0: {} + pretty-format@29.7.0: dependencies: '@jest/schemas': 29.6.3 @@ -21860,7 +22483,7 @@ snapshots: proxy-agent@6.5.0: dependencies: agent-base: 7.1.4 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 lru-cache: 7.18.3 @@ -21870,6 +22493,8 @@ snapshots: transitivePeerDependencies: - supports-color + proxy-from-env@1.0.0: {} + proxy-from-env@1.1.0: {} proxy-from-env@2.1.0: {} @@ -21887,7 +22512,7 @@ snapshots: dependencies: '@puppeteer/browsers': 2.13.2 chromium-bidi: 14.0.0(devtools-protocol@0.0.1608973) - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) devtools-protocol: 0.0.1608973 typed-query-selector: 2.12.2 webdriver-bidi-protocol: 0.4.1 @@ -22127,6 +22752,15 @@ snapshots: - '@babel/core' - react-is + react-css-nocode-editor@1.0.13(react-dom@19.2.6(react@19.2.6))(react-is@19.2.7)(react@19.2.6): + dependencies: + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) + styled-components: 5.3.11(react-dom@19.2.6(react@19.2.6))(react-is@19.2.7)(react@19.2.6) + transitivePeerDependencies: + - '@babel/core' + - react-is + react-day-picker@8.10.2(date-fns@3.6.0)(react@19.2.6): dependencies: date-fns: 3.6.0 @@ -22568,6 +23202,10 @@ snapshots: repeat-string@1.6.1: {} + request-progress@3.0.0: + dependencies: + throttleit: 1.0.1 + require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -22688,7 +23326,7 @@ snapshots: router@2.2.0: dependencies: - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) depd: 2.0.0 is-promise: 4.0.0 parseurl: 1.3.3 @@ -22806,7 +23444,7 @@ snapshots: send@1.2.1: dependencies: - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -22990,6 +23628,11 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 + slice-ansi@8.0.0: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + smart-buffer@4.2.0: {} smob@1.6.2: {} @@ -23019,7 +23662,7 @@ snapshots: socket.io-adapter@2.5.8: dependencies: - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) ws: 8.21.0 transitivePeerDependencies: - bufferutil @@ -23029,7 +23672,7 @@ snapshots: socket.io-client@4.8.3: dependencies: '@socket.io/component-emitter': 3.1.2 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) engine.io-client: 6.6.5 socket.io-parser: 4.2.6 transitivePeerDependencies: @@ -23040,7 +23683,7 @@ snapshots: socket.io-parser@4.2.6: dependencies: '@socket.io/component-emitter': 3.1.2 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -23049,7 +23692,7 @@ snapshots: accepts: 1.3.8 base64id: 2.0.0 cors: 2.8.6 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) engine.io: 6.6.9 socket.io-adapter: 2.5.8 socket.io-parser: 4.2.6 @@ -23061,7 +23704,7 @@ snapshots: socks-proxy-agent@8.0.5: dependencies: agent-base: 7.1.4 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) socks: 2.8.9 transitivePeerDependencies: - supports-color @@ -23122,6 +23765,18 @@ snapshots: dependencies: frac: 1.1.2 + sshpk@1.18.0: + dependencies: + asn1: 0.2.6 + assert-plus: 1.0.0 + bcrypt-pbkdf: 1.0.2 + dashdash: 1.14.1 + ecc-jsbn: 0.1.2 + getpass: 0.1.7 + jsbn: 0.1.1 + safer-buffer: 2.1.2 + tweetnacl: 0.14.5 + stable-hash@0.0.5: {} stack-trace@0.0.10: {} @@ -23202,6 +23857,11 @@ snapshots: get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 + string-width@8.2.2: + dependencies: + get-east-asian-width: 1.6.0 + strip-ansi: 7.2.0 + string.prototype.includes@2.0.1: dependencies: call-bind: 1.0.9 @@ -23324,6 +23984,24 @@ snapshots: transitivePeerDependencies: - '@babel/core' + styled-components@5.3.11(react-dom@19.2.6(react@19.2.6))(react-is@19.2.7)(react@19.2.6): + dependencies: + '@babel/helper-module-imports': 7.29.7(supports-color@5.5.0) + '@babel/traverse': 7.29.7(supports-color@5.5.0) + '@emotion/is-prop-valid': 1.4.0 + '@emotion/stylis': 0.8.5 + '@emotion/unitless': 0.7.5 + babel-plugin-styled-components: 2.3.0(styled-components@5.3.11(react-dom@19.2.6(react@19.2.6))(react-is@19.2.7)(react@19.2.6))(supports-color@5.5.0) + css-to-react-native: 3.2.0 + hoist-non-react-statics: 3.3.2 + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) + react-is: 19.2.7 + shallowequal: 1.1.0 + supports-color: 5.5.0 + transitivePeerDependencies: + - '@babel/core' + styled-jsx@5.1.1(babel-plugin-macros@3.1.0)(react@18.3.1): dependencies: client-only: 0.0.1 @@ -23349,7 +24027,7 @@ snapshots: dependencies: component-emitter: 1.3.1 cookiejar: 2.1.4 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) fast-safe-stringify: 2.1.1 form-data: 4.0.5 formidable: 3.5.4 @@ -23403,6 +24081,8 @@ snapshots: symbol-tree@3.2.4: {} + systeminformation@5.33.0: {} + tabbable@6.4.0: {} tagged-tag@1.0.0: {} @@ -23530,6 +24210,8 @@ snapshots: dependencies: any-promise: 1.3.0 + throttleit@1.0.1: {} + through2@2.0.5: dependencies: readable-stream: 2.3.8 @@ -23639,6 +24321,8 @@ snapshots: traverse@0.3.9: {} + tree-kill@1.2.2: {} + trim-canvas@0.1.2: {} ts-api-utils@2.5.0(typescript@5.9.3): @@ -23743,6 +24427,10 @@ snapshots: tslib@2.8.1: {} + tunnel-agent@0.6.0: + dependencies: + safe-buffer: 5.2.1 + turbo@2.9.16: optionalDependencies: '@turbo/darwin-64': 2.9.16 @@ -23754,6 +24442,8 @@ snapshots: tw-animate-css@1.4.0: {} + tweetnacl@0.14.5: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -23764,6 +24454,8 @@ snapshots: type-fest@0.21.3: {} + type-fest@0.8.1: {} + type-fest@4.41.0: {} type-fest@5.7.0: @@ -23842,7 +24534,7 @@ snapshots: app-root-path: 3.1.0 buffer: 6.0.3 dayjs: 1.11.21 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) dedent: 1.7.2(babel-plugin-macros@3.1.0) dotenv: 16.6.1 glob: 10.5.0 @@ -23866,7 +24558,7 @@ snapshots: app-root-path: 3.1.0 buffer: 6.0.3 dayjs: 1.11.21 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) dedent: 1.7.2(babel-plugin-macros@3.1.0) dotenv: 16.6.1 glob: 10.5.0 @@ -23968,6 +24660,8 @@ snapshots: until-async@3.0.2: {} + untildify@4.0.0: {} + unzipper@0.10.14: dependencies: big-integer: 1.6.52 @@ -24118,6 +24812,12 @@ snapshots: - '@types/react' - '@types/react-dom' + verror@1.10.0: + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.3.0 + victory-vendor@36.9.2: dependencies: '@types/d3-array': 3.2.2 @@ -24161,7 +24861,7 @@ snapshots: vite-node@2.1.9(@types/node@24.13.1)(lightningcss@1.32.0)(terser@5.48.0): dependencies: cac: 6.7.14 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) es-module-lexer: 1.7.0 pathe: 1.1.2 vite: 5.4.21(@types/node@24.13.1)(lightningcss@1.32.0)(terser@5.48.0) @@ -24197,7 +24897,7 @@ snapshots: '@vitest/spy': 2.1.9 '@vitest/utils': 2.1.9 chai: 5.3.3 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3(supports-color@8.1.1) expect-type: 1.3.0 magic-string: 0.30.21 pathe: 1.1.2 @@ -24538,6 +25238,10 @@ snapshots: buffer-crc32: 0.2.13 fd-slicer: 1.1.0 + yauzl@3.4.0: + dependencies: + pend: 1.2.0 + year@0.2.1: {} yn@3.1.1: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ecf919f09..e5e748478 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -4,6 +4,7 @@ packages: - "apps/edr-passenger-web/*" - "packages/*" - "packages/config/*" + - "e2e/*" verifyDepsBeforeRun: warn allowBuilds: "@nestjs/core": true @@ -14,6 +15,7 @@ allowBuilds: argon2: true bcrypt: true core-js: true + cypress: true es5-ext: true esbuild: true highlight.js: true