From 157dc97cd46a64fa20ba391892904da8e34d3446 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Wed, 17 Jul 2024 18:12:21 +0200 Subject: [PATCH 01/49] Add e2e tests and bump versions --- .github/workflows/extension-PR.yaml | 4 + .github/workflows/extension.yaml | 4 + .../static/manifest.json | 2 +- holo-key-manager-js-client/package.json | 2 +- .../tests/index.test.ts | 8 +- holo-key-manager-js-client/tests/test.html | 68 + package.json | 29 +- pnpm-lock.yaml | 1857 +++++++++++------ tests/clientInteraction.ts | 100 + tests/helpers.ts | 100 +- tests/index.test.ts | 173 +- tests/needsSetup.ts | 19 + tests/preventSignatureFromOtherOrigin.ts | 59 + tests/setupFlow.ts | 116 + tests/tsconfig.json | 4 + vitest.config.ts | 6 + 16 files changed, 1709 insertions(+), 842 deletions(-) create mode 100644 holo-key-manager-js-client/tests/test.html create mode 100644 tests/clientInteraction.ts create mode 100644 tests/needsSetup.ts create mode 100644 tests/preventSignatureFromOtherOrigin.ts create mode 100644 tests/setupFlow.ts create mode 100644 tests/tsconfig.json diff --git a/.github/workflows/extension-PR.yaml b/.github/workflows/extension-PR.yaml index 06baebf..6db9e03 100644 --- a/.github/workflows/extension-PR.yaml +++ b/.github/workflows/extension-PR.yaml @@ -33,6 +33,10 @@ jobs: run: pnpm build working-directory: holo-key-manager-extension + - name: Build and pack client + run: pnpm buildPack + working-directory: holo-key-manager-js-client + - name: Run e2e tests run: pnpm e2e-tests env: diff --git a/.github/workflows/extension.yaml b/.github/workflows/extension.yaml index 15d851b..aa1389c 100644 --- a/.github/workflows/extension.yaml +++ b/.github/workflows/extension.yaml @@ -71,6 +71,10 @@ jobs: run: pnpm build working-directory: holo-key-manager-extension + - name: Build and pack client + run: pnpm buildPack + working-directory: holo-key-manager-js-client + - name: Run e2e tests run: pnpm e2e-tests env: diff --git a/holo-key-manager-extension/static/manifest.json b/holo-key-manager-extension/static/manifest.json index 7c464b9..23a450b 100644 --- a/holo-key-manager-extension/static/manifest.json +++ b/holo-key-manager-extension/static/manifest.json @@ -1,7 +1,7 @@ { "name": "Holo key manager", "description": "A browser extension to manage holo keys", - "version": "0.0.74", + "version": "0.0.75", "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiAtKvbHNTN3O2BLRZH7RkLczaMLenSeZu+YP+KomPQPZ18nt4DY9boIN/+GWts7gCzEeQq59l8edGdF2P7xAbsRxYR88+zFEbxMtIyfyqJZIlzXwnvPJkwGu/S6arNtX48K7q1+xnJEE7VyeYSj6/i2LR+LmPigCzY9JCP7+SmWVeYbdm3kZmReK0ecfh15RXSNjZpXJUgrbea/RVxweggYKnmhhOUBmuJSCLoWTXIuJPBMwGQK1O2GKBqHOq94bPVSF7j+4WzSpPan70ZZJX/reFsOFE/idfFN6wbizjR1Ne50Po03kudEmfQgoqUhVpd0wP8A3YbqE7ODdZcCPPwIDAQAB", "manifest_version": 3, "action": { diff --git a/holo-key-manager-js-client/package.json b/holo-key-manager-js-client/package.json index b05f4e9..026f126 100644 --- a/holo-key-manager-js-client/package.json +++ b/holo-key-manager-js-client/package.json @@ -1,6 +1,6 @@ { "name": "@holo-host/holo-key-manager-js-client", - "version": "0.0.6", + "version": "0.0.7", "description": "A JavaScript client API for managing Holo keys", "main": "lib/index.js", "types": "lib/holo-key-manager-js-client/src/index.d.ts", diff --git a/holo-key-manager-js-client/tests/index.test.ts b/holo-key-manager-js-client/tests/index.test.ts index bcc723b..b6d107d 100644 --- a/holo-key-manager-js-client/tests/index.test.ts +++ b/holo-key-manager-js-client/tests/index.test.ts @@ -10,16 +10,16 @@ vi.mock('../src/helpers', async (importOriginal) => { const actual = await importOriginal(); return { ...(typeof actual === 'object' && actual !== null ? actual : {}), - sendMessage: vi.fn(), - parseMessagePayload: vi.fn(), + sendMessage: vi.fn(), + parseMessagePayload: vi.fn(), checkContentScriptAndBrowser: vi.fn() }; }); describe('createHoloKeyManager', () => { let holoKeyManager: ReturnType; - let sendMessageMock: Mock; - let parseMessagePayloadMock: Mock; + let sendMessageMock: Mock; + let parseMessagePayloadMock: Mock; beforeEach(() => { holoKeyManager = createHoloKeyManager(config); diff --git a/holo-key-manager-js-client/tests/test.html b/holo-key-manager-js-client/tests/test.html new file mode 100644 index 0000000..9606510 --- /dev/null +++ b/holo-key-manager-js-client/tests/test.html @@ -0,0 +1,68 @@ + + + + + Library Test + + + +
+ +

+ +

+ + +

+ +

+
+ + diff --git a/package.json b/package.json index 06d66ff..9947230 100644 --- a/package.json +++ b/package.json @@ -23,26 +23,29 @@ "devDependencies": { "@rollup/plugin-node-resolve": "^15.2.3", "@types/chrome": "^0.0.268", - "@typescript-eslint/parser": "^7.13.0", + "@types/express": "^4.17.21", + "@typescript-eslint/parser": "^7.16.1", "concurrently": "^8.2.2", "dotenv": "^16.4.5", - "eslint": "^9.4.0", + "eslint": "^9.7.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-simple-import-sort": "^12.1.0", - "eslint-plugin-svelte": "^2.39.3", - "globals": "^15.4.0", - "husky": "^9.0.11", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-simple-import-sort": "^12.1.1", + "eslint-plugin-svelte": "^2.42.0", + "express": "^4.19.2", + "globals": "^15.8.0", + "husky": "^9.1.0", "jszip": "^3.10.1", "lint-staged": "^15.2.5", - "prettier": "^3.3.2", - "puppeteer": "^22.12.0", - "rollup": "^4.18.0", + "prettier": "^3.3.3", + "puppeteer": "^22.13.1", + "rollup": "^4.18.1", "rollup-plugin-tsc-alias": "^1.1.2", "rollup-plugin-typescript2": "^0.36.0", - "typescript": "^5.4.5", - "typescript-eslint": "^7.13.0", - "vitest": "^1.6.0" + "tweetnacl": "^1.0.3", + "typescript": "^5.5.3", + "typescript-eslint": "^7.16.1", + "vitest": "^2.0.3" }, "dependencies": { "zod": "^3.23.8" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3199100..9633ed2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,13 +14,16 @@ importers: devDependencies: '@rollup/plugin-node-resolve': specifier: ^15.2.3 - version: 15.2.3(rollup@4.18.0) + version: 15.2.3(rollup@4.18.1) '@types/chrome': specifier: ^0.0.268 version: 0.0.268 + '@types/express': + specifier: ^4.17.21 + version: 4.17.21 '@typescript-eslint/parser': - specifier: ^7.13.0 - version: 7.13.1(eslint@9.5.0)(typescript@5.4.5) + specifier: ^7.16.1 + version: 7.16.1(eslint@9.7.0)(typescript@5.5.3) concurrently: specifier: ^8.2.2 version: 8.2.2 @@ -28,26 +31,29 @@ importers: specifier: ^16.4.5 version: 16.4.5 eslint: - specifier: ^9.4.0 - version: 9.5.0 + specifier: ^9.7.0 + version: 9.7.0 eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.0(eslint@9.5.0) + version: 9.1.0(eslint@9.7.0) eslint-plugin-prettier: - specifier: ^5.1.3 - version: 5.1.3(eslint-config-prettier@9.1.0(eslint@9.5.0))(eslint@9.5.0)(prettier@3.3.2) + specifier: ^5.2.1 + version: 5.2.1(eslint-config-prettier@9.1.0(eslint@9.7.0))(eslint@9.7.0)(prettier@3.3.3) eslint-plugin-simple-import-sort: - specifier: ^12.1.0 - version: 12.1.0(eslint@9.5.0) + specifier: ^12.1.1 + version: 12.1.1(eslint@9.7.0) eslint-plugin-svelte: - specifier: ^2.39.3 - version: 2.40.0(eslint@9.5.0)(svelte@4.2.18) + specifier: ^2.42.0 + version: 2.42.0(eslint@9.7.0)(svelte@4.2.18) + express: + specifier: ^4.19.2 + version: 4.19.2 globals: - specifier: ^15.4.0 - version: 15.6.0 + specifier: ^15.8.0 + version: 15.8.0 husky: - specifier: ^9.0.11 - version: 9.0.11 + specifier: ^9.1.0 + version: 9.1.0 jszip: specifier: ^3.10.1 version: 3.10.1 @@ -55,44 +61,47 @@ importers: specifier: ^15.2.5 version: 15.2.7 prettier: - specifier: ^3.3.2 - version: 3.3.2 + specifier: ^3.3.3 + version: 3.3.3 puppeteer: - specifier: ^22.12.0 - version: 22.12.0(typescript@5.4.5) + specifier: ^22.13.1 + version: 22.13.1(typescript@5.5.3) rollup: - specifier: ^4.18.0 - version: 4.18.0 + specifier: ^4.18.1 + version: 4.18.1 rollup-plugin-tsc-alias: specifier: ^1.1.2 - version: 1.1.2(rollup@4.18.0) + version: 1.1.2(rollup@4.18.1) rollup-plugin-typescript2: specifier: ^0.36.0 - version: 0.36.0(rollup@4.18.0)(typescript@5.4.5) + version: 0.36.0(rollup@4.18.1)(typescript@5.5.3) + tweetnacl: + specifier: ^1.0.3 + version: 1.0.3 typescript: - specifier: ^5.4.5 - version: 5.4.5 + specifier: ^5.5.3 + version: 5.5.3 typescript-eslint: - specifier: ^7.13.0 - version: 7.13.1(eslint@9.5.0)(typescript@5.4.5) + specifier: ^7.16.1 + version: 7.16.1(eslint@9.7.0)(typescript@5.5.3) vitest: - specifier: ^1.6.0 - version: 1.6.0(@types/node@20.14.8)(@vitest/ui@1.6.0)(terser@5.31.0) + specifier: ^2.0.3 + version: 2.0.3(@types/node@20.14.11)(@vitest/ui@2.0.3)(terser@5.31.3) holo-key-manager-extension: dependencies: '@holochain/client': specifier: 0.17.0 - version: 0.17.0 + version: 0.18.0-dev.6 '@holochain/hc-seed-bundle': specifier: 0.1.1 - version: 0.1.1(typescript@5.4.5) + version: 0.1.1(typescript@5.5.3) '@msgpack/msgpack': specifier: 3.0.0-beta2 version: 3.0.0-beta2 '@tanstack/svelte-query': specifier: ^5.46.1 - version: 5.46.1(svelte@4.2.18) + version: 5.51.5(svelte@4.2.18) blakejs: specifier: ^1.2.1 version: 1.2.1 @@ -110,44 +119,44 @@ importers: version: 4.2.18 tailwindcss: specifier: ^3.4.4 - version: 3.4.4 + version: 3.4.6 tiny-glob: specifier: ^0.2.9 version: 0.2.9 devDependencies: '@sveltejs/adapter-static': specifier: ^3.0.2 - version: 3.0.2(@sveltejs/kit@2.5.17(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)))(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0))) + version: 3.0.2(@sveltejs/kit@2.5.18(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)))(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3))) '@sveltejs/kit': specifier: ^2.5.10 - version: 2.5.17(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)))(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)) + version: 2.5.18(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)))(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)) '@sveltejs/vite-plugin-svelte': specifier: ^3.1.1 - version: 3.1.1(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)) + version: 3.1.1(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)) '@types/file-saver': specifier: ^2.0.7 version: 2.0.7 '@vitest/ui': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 2.0.3(vitest@2.0.3) archiver: specifier: ^7.0.1 version: 7.0.1 autoprefixer: specifier: ^10.4.19 - version: 10.4.19(postcss@8.4.38) + version: 10.4.19(postcss@8.4.39) postcss: specifier: ^8.4.38 - version: 8.4.38 + version: 8.4.39 prettier-plugin-svelte: specifier: ^3.2.5 - version: 3.2.5(prettier@3.3.2)(svelte@4.2.18) + version: 3.2.6(prettier@3.3.3)(svelte@4.2.18) prettier-plugin-tailwindcss: specifier: ^0.6.2 - version: 0.6.5(prettier-plugin-svelte@3.2.5(prettier@3.3.2)(svelte@4.2.18))(prettier@3.3.2) + version: 0.6.5(prettier-plugin-svelte@3.2.6(prettier@3.3.3)(svelte@4.2.18))(prettier@3.3.3) svelte-check: specifier: ^3.8.0 - version: 3.8.1(postcss-load-config@4.0.2(postcss@8.4.38))(postcss@8.4.38)(svelte@4.2.18) + version: 3.8.4(postcss-load-config@6.0.1(postcss@8.4.39))(postcss@8.4.39)(svelte@4.2.18) svelte-file-dropzone: specifier: ^2.0.7 version: 2.0.7(svelte@4.2.18) @@ -156,25 +165,25 @@ importers: version: 2.6.3 vite: specifier: ^5.2.13 - version: 5.3.1(@types/node@20.14.8)(terser@5.31.0) + version: 5.3.4(@types/node@20.14.11)(terser@5.31.3) holo-key-manager-extension/scripts: devDependencies: '@rollup/plugin-commonjs': specifier: ^26.0.1 - version: 26.0.1(rollup@4.18.0) + version: 26.0.1(rollup@4.18.1) '@rollup/plugin-inject': specifier: ^5.0.5 - version: 5.0.5(rollup@4.18.0) + version: 5.0.5(rollup@4.18.1) '@rollup/plugin-node-resolve': specifier: ^15.2.3 - version: 15.2.3(rollup@4.18.0) + version: 15.2.3(rollup@4.18.1) '@rollup/plugin-replace': specifier: ^5.0.7 - version: 5.0.7(rollup@4.18.0) + version: 5.0.7(rollup@4.18.1) '@rollup/plugin-terser': specifier: ^0.4.4 - version: 0.4.4(rollup@4.18.0) + version: 0.4.4(rollup@4.18.1) buffer: specifier: ^6.0.3 version: 6.0.3 @@ -366,28 +375,28 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.10.0': - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + '@eslint-community/regexpp@4.11.0': + resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.16.0': - resolution: {integrity: sha512-/jmuSd74i4Czf1XXn7wGRWZCuyaUZ330NH1Bek0Pplatt4Sy1S5haN21SCLLdbeKslQ+S0wEJ+++v5YibSi+Lg==} + '@eslint/config-array@0.17.0': + resolution: {integrity: sha512-A68TBu6/1mHHuc5YJL0U0VVeGNiklLAL6rRmhTCP2B5XjWLMnrX+HkO+IAXyHvks5cyyY1jjK5ITPQ1HGS2EVA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.1.0': resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.5.0': - resolution: {integrity: sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==} + '@eslint/js@9.7.0': + resolution: {integrity: sha512-ChuWDQenef8OSFnvuxv0TCVxEwmu3+hPNKvM9B34qpM0rDRbjL8t5QkQeHHeAfsKQjuH9wS82WeCi1J/owatng==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.4': resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@holochain/client@0.17.0': - resolution: {integrity: sha512-jDIv2kjfa+oBiQO7wjl09ELaPbVFoNu7f+2Sk3aLdf5AfVE/O8C6iZFGtF1huLKDJM8LPjRlKrt/Obt5ThMhbQ==} + '@holochain/client@0.18.0-dev.6': + resolution: {integrity: sha512-6NZjXEepN4UXXgBDIy3pL/a0yDQFhWwFk9fAEgZl2jTXlpWwvQZ++5d1KinAcfHgZvBNo3807LhJoydyv9XIwg==} engines: {node: '>=18.0.0 || >=20.0.0'} '@holochain/hc-seed-bundle@0.1.1': @@ -410,10 +419,6 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} - '@jest/schemas@29.6.3': - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} @@ -432,6 +437,9 @@ packages: '@jridgewell/sourcemap-codec@1.4.15': resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} @@ -470,8 +478,8 @@ packages: '@polka/url@1.0.0-next.25': resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} - '@puppeteer/browsers@2.2.3': - resolution: {integrity: sha512-bJ0UBsk0ESOs6RFcLXOt99a3yTDcOKlzfjad+rhFwdaG1Lu/Wzq58GHYCDTlZ9z6mldf4g+NTb+TXEfe0PpnsQ==} + '@puppeteer/browsers@2.2.4': + resolution: {integrity: sha512-BdG2qiI1dn89OTUUsx2GZSpUzW+DRffR1wlMJyKxVHYrhnKoELSDxDd+2XImUkuWPEKk76H5FcM/gPFrEK1Tfw==} engines: {node: '>=18'} hasBin: true @@ -533,96 +541,93 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.18.0': - resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} + '@rollup/rollup-android-arm-eabi@4.18.1': + resolution: {integrity: sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.18.0': - resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} + '@rollup/rollup-android-arm64@4.18.1': + resolution: {integrity: sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.18.0': - resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} + '@rollup/rollup-darwin-arm64@4.18.1': + resolution: {integrity: sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.18.0': - resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} + '@rollup/rollup-darwin-x64@4.18.1': + resolution: {integrity: sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.18.0': - resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} + '@rollup/rollup-linux-arm-gnueabihf@4.18.1': + resolution: {integrity: sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.18.0': - resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} + '@rollup/rollup-linux-arm-musleabihf@4.18.1': + resolution: {integrity: sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.18.0': - resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} + '@rollup/rollup-linux-arm64-gnu@4.18.1': + resolution: {integrity: sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.18.0': - resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} + '@rollup/rollup-linux-arm64-musl@4.18.1': + resolution: {integrity: sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': - resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} + '@rollup/rollup-linux-powerpc64le-gnu@4.18.1': + resolution: {integrity: sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.18.0': - resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} + '@rollup/rollup-linux-riscv64-gnu@4.18.1': + resolution: {integrity: sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.18.0': - resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} + '@rollup/rollup-linux-s390x-gnu@4.18.1': + resolution: {integrity: sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.18.0': - resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} + '@rollup/rollup-linux-x64-gnu@4.18.1': + resolution: {integrity: sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.18.0': - resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} + '@rollup/rollup-linux-x64-musl@4.18.1': + resolution: {integrity: sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.18.0': - resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} + '@rollup/rollup-win32-arm64-msvc@4.18.1': + resolution: {integrity: sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.18.0': - resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} + '@rollup/rollup-win32-ia32-msvc@4.18.1': + resolution: {integrity: sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.18.0': - resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} + '@rollup/rollup-win32-x64-msvc@4.18.1': + resolution: {integrity: sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==} cpu: [x64] os: [win32] - '@sinclair/typebox@0.27.8': - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - '@sveltejs/adapter-static@3.0.2': resolution: {integrity: sha512-/EBFydZDwfwFfFEuF1vzUseBoRziwKP7AoHAwv+Ot3M084sE/HTVBHf9mCmXfdM9ijprY5YEugZjleflncX5fQ==} peerDependencies: '@sveltejs/kit': ^2.0.0 - '@sveltejs/kit@2.5.17': - resolution: {integrity: sha512-wiADwq7VreR3ctOyxilAZOfPz3Jiy2IIp2C8gfafhTdQaVuGIHllfqQm8dXZKADymKr3uShxzgLZFT+a+CM4kA==} + '@sveltejs/kit@2.5.18': + resolution: {integrity: sha512-+g06hvpVAnH7b4CDjhnTDgFWBKBiQJpuSmQeGYOuzbO3SC3tdYjRNlDCrafvDtKbGiT2uxY5Dn9qdEUGVZdWOQ==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -645,26 +650,38 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.0 - '@tanstack/query-core@5.45.0': - resolution: {integrity: sha512-RVfIZQmFUTdjhSAAblvueimfngYyfN6HlwaJUPK71PKd7yi43Vs1S/rdimmZedPWX/WGppcq/U1HOj7O7FwYxw==} + '@tanstack/query-core@5.51.5': + resolution: {integrity: sha512-qovOto6hFet2zA4Pf3cDO+qkOqskO6xP39PlKnr6YKPtjRsePWyZnTaMf59+VnlOLY8gpku1I4WPC4dqBXo4FQ==} - '@tanstack/svelte-query@5.46.1': - resolution: {integrity: sha512-6zu4jJo8fqsgDJidI8IC68o9HEDpqvY7GoopNCb/AUIL2ZfbdHJ+ZeN4mndP/+zb9Yw9ZF/schXspB0LQfCqtw==} + '@tanstack/svelte-query@5.51.5': + resolution: {integrity: sha512-6POqaWbhmkyFosZfA9lYJC5q+pehWQ6Ykkxq+s5wgrHdSAMw/q9t124Z92WcK7YTia5GXMJ0OTNsprh64ZFw8g==} peerDependencies: svelte: ^3.54.0 || ^4.0.0 || ^5.0.0-next.0 '@tootallnate/quickjs-emscripten@0.23.0': resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + '@types/body-parser@1.19.5': + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + '@types/chrome@0.0.268': resolution: {integrity: sha512-7N1QH9buudSJ7sI8Pe4mBHJr5oZ48s0hcanI9w3wgijAlv1OZNUZve9JR4x42dn5lJ5Sm87V1JNfnoh10EnQlA==} + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/express-serve-static-core@4.19.5': + resolution: {integrity: sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==} + + '@types/express@4.17.21': + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + '@types/file-saver@2.0.7': resolution: {integrity: sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==} @@ -677,20 +694,41 @@ packages: '@types/har-format@1.2.15': resolution: {integrity: sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==} + '@types/http-errors@2.0.4': + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + + '@types/node@20.14.11': + resolution: {integrity: sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==} + '@types/node@20.14.8': resolution: {integrity: sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA==} '@types/pug@2.0.10': resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==} + '@types/qs@6.9.15': + resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + '@types/send@0.17.4': + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + + '@types/serve-static@1.15.7': + resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@7.13.1': - resolution: {integrity: sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==} + '@typescript-eslint/eslint-plugin@7.16.1': + resolution: {integrity: sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: '@typescript-eslint/parser': ^7.0.0 @@ -700,8 +738,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@7.13.1': - resolution: {integrity: sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==} + '@typescript-eslint/parser@7.16.1': + resolution: {integrity: sha512-u+1Qx86jfGQ5i4JjK33/FnawZRpsLxRnKzGE6EABZ40KxVT/vWsiZFEBBHjFOljmmV3MBYOHEKi0Jm9hbAOClA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -710,12 +748,12 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@7.13.1': - resolution: {integrity: sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==} + '@typescript-eslint/scope-manager@7.16.1': + resolution: {integrity: sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/type-utils@7.13.1': - resolution: {integrity: sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==} + '@typescript-eslint/type-utils@7.16.1': + resolution: {integrity: sha512-rbu/H2MWXN4SkjIIyWcmYBjlp55VT+1G3duFOIukTNFxr9PI35pLc2ydwAfejCEitCv4uztA07q0QWanOHC7dA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -724,12 +762,12 @@ packages: typescript: optional: true - '@typescript-eslint/types@7.13.1': - resolution: {integrity: sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==} + '@typescript-eslint/types@7.16.1': + resolution: {integrity: sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/typescript-estree@7.13.1': - resolution: {integrity: sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==} + '@typescript-eslint/typescript-estree@7.16.1': + resolution: {integrity: sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' @@ -737,56 +775,59 @@ packages: typescript: optional: true - '@typescript-eslint/utils@7.13.1': - resolution: {integrity: sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==} + '@typescript-eslint/utils@7.16.1': + resolution: {integrity: sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 - '@typescript-eslint/visitor-keys@7.13.1': - resolution: {integrity: sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==} + '@typescript-eslint/visitor-keys@7.16.1': + resolution: {integrity: sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg==} engines: {node: ^18.18.0 || >=20.0.0} - '@vitest/expect@1.6.0': - resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} + '@vitest/expect@2.0.3': + resolution: {integrity: sha512-X6AepoOYePM0lDNUPsGXTxgXZAl3EXd0GYe/MZyVE4HzkUqyUVC6S3PrY5mClDJ6/7/7vALLMV3+xD/Ko60Hqg==} + + '@vitest/pretty-format@2.0.3': + resolution: {integrity: sha512-URM4GLsB2xD37nnTyvf6kfObFafxmycCL8un3OC9gaCs5cti2u+5rJdIflZ2fUJUen4NbvF6jCufwViAFLvz1g==} - '@vitest/runner@1.6.0': - resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} + '@vitest/runner@2.0.3': + resolution: {integrity: sha512-EmSP4mcjYhAcuBWwqgpjR3FYVeiA4ROzRunqKltWjBfLNs1tnMLtF+qtgd5ClTwkDP6/DGlKJTNa6WxNK0bNYQ==} - '@vitest/snapshot@1.6.0': - resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} + '@vitest/snapshot@2.0.3': + resolution: {integrity: sha512-6OyA6v65Oe3tTzoSuRPcU6kh9m+mPL1vQ2jDlPdn9IQoUxl8rXhBnfICNOC+vwxWY684Vt5UPgtcA2aPFBb6wg==} - '@vitest/spy@1.6.0': - resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} + '@vitest/spy@2.0.3': + resolution: {integrity: sha512-sfqyAw/ypOXlaj4S+w8689qKM1OyPOqnonqOc9T91DsoHbfN5mU7FdifWWv3MtQFf0lEUstEwR9L/q/M390C+A==} - '@vitest/ui@1.6.0': - resolution: {integrity: sha512-k3Lyo+ONLOgylctiGovRKy7V4+dIN2yxstX3eY5cWFXH6WP+ooVX79YSyi0GagdTQzLmT43BF27T0s6dOIPBXA==} + '@vitest/ui@2.0.3': + resolution: {integrity: sha512-UAkzHk5veR3NRF7BNUxWlLly7Cw7H+wzP3+eiMIVeKo3Md33Ey20rYsNQn/9McIqOeO02tMzqHhpThmjk1yRzw==} peerDependencies: - vitest: 1.6.0 + vitest: 2.0.3 - '@vitest/utils@1.6.0': - resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} + '@vitest/utils@2.0.3': + resolution: {integrity: sha512-c/UdELMuHitQbbc/EVctlBaxoYAwQPQdSNwv7z/vHyBKy2edYZaFgptE27BRueZB7eW8po+cllotMNTDpL3HWg==} abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn-walk@8.3.3: - resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==} - engines: {node: '>=0.4.0'} - acorn@8.11.3: resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} engines: {node: '>=0.4.0'} hasBin: true - acorn@8.12.0: - resolution: {integrity: sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==} + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} engines: {node: '>=0.4.0'} hasBin: true @@ -817,10 +858,6 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} @@ -849,12 +886,16 @@ packages: aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} ast-types@0.13.4: resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} @@ -908,6 +949,10 @@ packages: blakejs@1.2.1: resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} + body-parser@1.20.2: + resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -943,10 +988,18 @@ packages: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -958,9 +1011,9 @@ packages: caniuse-lite@1.0.30001620: resolution: {integrity: sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==} - chai@4.4.1: - resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} - engines: {node: '>=4'} + chai@5.1.1: + resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==} + engines: {node: '>=12'} chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -974,15 +1027,16 @@ packages: resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} - chromium-bidi@0.5.24: - resolution: {integrity: sha512-5xQNN2SVBdZv4TxeMLaI+PelrnZsHDhn8h2JtyriLr+0qHcZS8BMuo93qN6J1VmtmrgYP+rmcLHcbpnA8QJh+w==} + chromium-bidi@0.6.1: + resolution: {integrity: sha512-kSxJRj0VgtUKz6nmzc2JPfyfJGzwzt65u7PqhPHtgGQUZLF5oG+ST6l6e5ONfStUMAlhSutFCjaGKllXZa16jA==} peerDependencies: devtools-protocol: '*' @@ -1051,8 +1105,16 @@ packages: engines: {node: ^14.13.0 || >=16.0.0} hasBin: true - confbox@0.1.7: - resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} cookie@0.6.0: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} @@ -1100,6 +1162,14 @@ packages: resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} engines: {node: '>=0.11'} + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -1118,8 +1188,8 @@ packages: supports-color: optional: true - deep-eql@4.1.4: - resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} deep-is@0.1.4: @@ -1129,14 +1199,26 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + degenerator@5.0.1: resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} engines: {node: '>= 14'} + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + detect-indent@6.1.0: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} @@ -1150,10 +1232,6 @@ packages: didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -1168,6 +1246,9 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + electron-to-chromium@1.4.776: resolution: {integrity: sha512-s694bi3+gUzlliqxjPHpa9NRTlhzTgB34aan+pVKZmOTGy2xoZXl+8E1B8i5p5rtev3PKMK/H4asgNejC+YHNg==} @@ -1184,6 +1265,10 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} @@ -1194,6 +1279,14 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + es6-promise@3.3.1: resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} @@ -1206,6 +1299,9 @@ packages: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} @@ -1231,8 +1327,8 @@ packages: peerDependencies: eslint: '>=7.0.0' - eslint-plugin-prettier@5.1.3: - resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} + eslint-plugin-prettier@5.2.1: + resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -1245,17 +1341,17 @@ packages: eslint-config-prettier: optional: true - eslint-plugin-simple-import-sort@12.1.0: - resolution: {integrity: sha512-Y2fqAfC11TcG/WP3TrI1Gi3p3nc8XJyEOJYHyEPEGI/UAgNx6akxxlX74p7SbAQdLcgASKhj8M0GKvH3vq/+ig==} + eslint-plugin-simple-import-sort@12.1.1: + resolution: {integrity: sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==} peerDependencies: eslint: '>=5.0.0' - eslint-plugin-svelte@2.40.0: - resolution: {integrity: sha512-JuOzmfVaMeEkBASL7smHu3tIU4D9rWkHuRNV+zm/5zgAwiZVvxrXM7TcfIOS+U7VXOr4uCZuE+kZTVTzS0IE+Q==} + eslint-plugin-svelte@2.42.0: + resolution: {integrity: sha512-mHP6z0DWq97KZvoQcApZHdF9m9epcDV/ICKufeEH18Vh+8vl7S+gwt8WdUohEqKNVMuXRkbvy1suMcVvUDiOGw==} engines: {node: ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0-0 || ^9.0.0-0 - svelte: ^3.37.0 || ^4.0.0 || ^5.0.0-next.155 + svelte: ^3.37.0 || ^4.0.0 || ^5.0.0-next.181 peerDependenciesMeta: svelte: optional: true @@ -1264,8 +1360,8 @@ packages: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-scope@8.0.1: - resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==} + eslint-scope@8.0.2: + resolution: {integrity: sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: @@ -1276,8 +1372,8 @@ packages: resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.5.0: - resolution: {integrity: sha512-+NAOZFrW/jFTS3dASCGBxX1pkFD0/fsO+hfAkJ4TyYKwgsXZbqzrw+seCYFCcPCYXvnD67tAnglU7GQTz6kcVw==} + eslint@9.7.0: + resolution: {integrity: sha512-FzJ9D/0nGiCGBf8UXO/IGLTgLVzIxze1zpfA8Ton2mjLovXdAPlYDv+MQDcqj3TmrhAGYfOpz9RfR+ent0AgAw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true @@ -1297,8 +1393,8 @@ packages: engines: {node: '>=4'} hasBin: true - esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} esrecurse@4.3.0: @@ -1322,6 +1418,10 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -1337,6 +1437,10 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} + express@4.19.2: + resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} + engines: {node: '>= 0.10.0'} + extract-zip@2.0.1: resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} engines: {node: '>= 10.17.0'} @@ -1385,6 +1489,10 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + finalhandler@1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + find-cache-dir@3.3.2: resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} engines: {node: '>=8'} @@ -1408,9 +1516,17 @@ packages: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -1441,6 +1557,10 @@ packages: get-func-name@2.0.2: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + get-stream@5.2.0: resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} engines: {node: '>=8'} @@ -1479,8 +1599,8 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - globals@15.6.0: - resolution: {integrity: sha512-UzcJi88Hw//CurUIRa9Jxb0vgOCcuD/MNjwmXp633cyaRKkCWACkoqHCtfZv43b1kqXGg/fpOa8bwgacCeXsVg==} + globals@15.8.0: + resolution: {integrity: sha512-VZAJ4cewHTExBWDHR6yptdIBlx9YSSZuwojj9Nt5mBRXQzrKakDsVKQ1J63sklLvzAJm0X5+RpO4i3Y2hcOnFw==} engines: {node: '>=18'} globalyzer@0.1.0: @@ -1493,6 +1613,9 @@ packages: globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -1507,27 +1630,46 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} - https-proxy-agent@7.0.4: - resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==} + https-proxy-agent@7.0.5: + resolution: {integrity: sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==} engines: {node: '>= 14'} human-signals@5.0.0: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} - husky@9.0.11: - resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} + husky@9.1.0: + resolution: {integrity: sha512-8XCjbomYTGdNF2h50dio3T3zghmZ9f/ZNzr99YwSkvDdhEjJGs5qzy8tbFx+SG8yCx2wn9nMVfZxVrr/yT8gNQ==} engines: {node: '>=18'} hasBin: true + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -1560,6 +1702,10 @@ packages: resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} engines: {node: '>= 12'} + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -1648,9 +1794,6 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-tokens@9.0.0: - resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} - js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -1683,8 +1826,8 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} - known-css-properties@0.32.0: - resolution: {integrity: sha512-PXuex21brpp7qENI143ZL5cWQcMR4IZVeeZv9ew6dg+bZX2xRUu/NzGKudZJY5DO4APiMkNPYIF8VGIdY08Tdw==} + known-css-properties@0.34.0: + resolution: {integrity: sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==} lazystream@1.0.1: resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} @@ -1717,6 +1860,10 @@ packages: resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==} engines: {node: '>=14'} + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -1729,10 +1876,6 @@ packages: resolution: {integrity: sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==} engines: {node: '>=18.0.0'} - local-pkg@0.5.0: - resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} - engines: {node: '>=14'} - locate-character@3.0.0: resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} @@ -1757,17 +1900,13 @@ packages: resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} engines: {node: '>=18'} - loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + loupe@3.1.1: + resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==} lru-cache@10.2.2: resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} engines: {node: 14 || >=16.14} - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - lru-cache@7.18.3: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} @@ -1785,6 +1924,13 @@ packages: mdn-data@2.0.30: resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -1792,6 +1938,10 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + micromatch@4.0.6: resolution: {integrity: sha512-Y4Ypn3oujJYxJcMacVgcs92wofTHxp9FzfDpQON4msDefoC0lb3ETvQLOdLcbhSwU1bz8HrL/1sygfBIHudrkQ==} engines: {node: '>=8.6'} @@ -1800,6 +1950,19 @@ packages: resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} engines: {node: '>=8.6'} + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -1823,6 +1986,10 @@ packages: resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} engines: {node: '>=16 || 14 >=14.17'} + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} @@ -1841,9 +2008,6 @@ packages: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true - mlly@1.7.1: - resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} - mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -1852,9 +2016,15 @@ packages: resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} engines: {node: '>=10'} + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mylas@2.1.13: resolution: {integrity: sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==} engines: {node: '>=12.0.0'} @@ -1876,6 +2046,10 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + netmask@2.0.2: resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} engines: {node: '>= 0.4.0'} @@ -1903,6 +2077,14 @@ packages: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} + object-inspect@1.13.2: + resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} + engines: {node: '>= 0.4'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -1926,10 +2108,6 @@ packages: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} - p-limit@5.0.0: - resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} - engines: {node: '>=18'} - p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -1942,8 +2120,8 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} - pac-proxy-agent@7.0.1: - resolution: {integrity: sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==} + pac-proxy-agent@7.0.2: + resolution: {integrity: sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==} engines: {node: '>= 14'} pac-resolver@7.0.1: @@ -1964,6 +2142,10 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -1987,6 +2169,9 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -1994,8 +2179,9 @@ packages: pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} @@ -2031,9 +2217,6 @@ packages: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} - pkg-types@1.1.1: - resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==} - plimit-lit@1.6.1: resolution: {integrity: sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==} engines: {node: '>=12'} @@ -2074,6 +2257,24 @@ packages: ts-node: optional: true + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} + peerDependencies: + jiti: '>=1.21.0' + postcss: '>=8.0.9' + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true + postcss-nested@6.0.1: resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} engines: {node: '>=12.0'} @@ -2096,15 +2297,15 @@ packages: resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==} engines: {node: '>=4'} - postcss-selector-parser@6.1.0: - resolution: {integrity: sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==} + postcss-selector-parser@6.1.1: + resolution: {integrity: sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==} engines: {node: '>=4'} postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.38: - resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + postcss@8.4.39: + resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -2115,8 +2316,8 @@ packages: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} - prettier-plugin-svelte@3.2.5: - resolution: {integrity: sha512-vP/M/Goc8z4iVIvrwXwbrYVjJgA0Hf8PO1G4LBh/ocSt6vUP6sLvyu9F3ABEGr+dbKyxZjEKLkeFsWy/yYl0HQ==} + prettier-plugin-svelte@3.2.6: + resolution: {integrity: sha512-Y1XWLw7vXUQQZmgv1JAEiLcErqUniAF2wO7QJsw8BVMvpLET2dI5WpEIEJx1r11iHVdSMzQxivyfrH9On9t2IQ==} peerDependencies: prettier: ^3.0.0 svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 @@ -2173,15 +2374,11 @@ packages: prettier-plugin-svelte: optional: true - prettier@3.3.2: - resolution: {integrity: sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==} + prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} engines: {node: '>=14'} hasBin: true - pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} @@ -2193,6 +2390,10 @@ packages: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + proxy-agent@6.4.0: resolution: {integrity: sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==} engines: {node: '>= 14'} @@ -2207,15 +2408,19 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - puppeteer-core@22.12.0: - resolution: {integrity: sha512-9gY+JwBW/Fp3/x9+cOGK7ZcwqjvtvY2xjqRqsAA0B3ZFMzBauVTSZ26iWTmvOQX2sk78TN/rd5rnetxVxmK5CQ==} + puppeteer-core@22.13.1: + resolution: {integrity: sha512-NmhnASYp51QPRCAf9n0OPxuPMmzkKd8+2sB9Q+BjwwCG25gz6iuNc3LQDWa+cH2tyivmJppLhNNFt6Q3HmoOpw==} engines: {node: '>=18'} - puppeteer@22.12.0: - resolution: {integrity: sha512-kyUYI12SyJIjf9UGTnHfhNMYv4oVK321Jb9QZDBiGVNx5453SplvbdKI7UrF+S//3RtCneuUFCyHxnvQXQjpxg==} + puppeteer@22.13.1: + resolution: {integrity: sha512-PwXLDQK5u83Fm5A7TGMq+9BR7iHDJ8a3h21PSsh/E6VfhxiKYkU7+tvGZNSCap6k3pCNDd9oNteVBEctcBalmQ==} engines: {node: '>=18'} hasBin: true + qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + queue-lit@1.5.2: resolution: {integrity: sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==} engines: {node: '>=12'} @@ -2229,8 +2434,13 @@ packages: randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} @@ -2301,8 +2511,8 @@ packages: rollup-pluginutils@2.8.2: resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} - rollup@4.18.0: - resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} + rollup@4.18.1: + resolution: {integrity: sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2322,6 +2532,9 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + sander@0.5.1: resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} @@ -2329,25 +2542,40 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} engines: {node: '>=10'} hasBin: true - semver@7.6.2: - resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} engines: {node: '>=10'} hasBin: true + send@0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + serve-static@1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + set-cookie-parser@2.6.0: resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -2359,6 +2587,10 @@ packages: shell-quote@1.8.1: resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} + side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -2392,8 +2624,8 @@ packages: smob@1.5.0: resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} - socks-proxy-agent@8.0.3: - resolution: {integrity: sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==} + socks-proxy-agent@8.0.4: + resolution: {integrity: sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==} engines: {node: '>= 14'} socks@2.8.3: @@ -2428,6 +2660,10 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + std-env@3.7.0: resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} @@ -2479,9 +2715,6 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strip-literal@2.1.0: - resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} - sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} @@ -2503,17 +2736,17 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - svelte-check@3.8.1: - resolution: {integrity: sha512-KlQ0TRVe01mdvh49Ylkr9FQxO/UWbQOtaIrccl3gjgkvby1TxY41VkT7ijCl6i29FjaJPE4m6YGmhdqov0MfkA==} + svelte-check@3.8.4: + resolution: {integrity: sha512-61aHMkdinWyH8BkkTX9jPLYxYzaAAz/FK/VQqdr2FiCQQ/q04WCwDlpGbHff1GdrMYTmW8chlTFvRWL9k0A8vg==} hasBin: true peerDependencies: svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 - svelte-eslint-parser@0.39.1: - resolution: {integrity: sha512-0VR9gq2TOdSrJW94Qf2F3XrzXRQomXQtRZGFS3FEUr3G4J8DcpqXfBF1HJyOa3dACyGsKiBbOPF56pBgYaqXBA==} + svelte-eslint-parser@0.40.0: + resolution: {integrity: sha512-M+v1HhC5T1WKYVxWexUCS4o6oIBS88XKzOZuhl2ew+eGxol7eC21e+VE8TC4rXJ3iT3iXT0qlZsZcpKjVo5/zQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - svelte: ^3.37.0 || ^4.0.0 || ^5.0.0-next.115 + svelte: ^3.37.0 || ^4.0.0 || ^5.0.0-next.181 peerDependenciesMeta: svelte: optional: true @@ -2570,17 +2803,17 @@ packages: resolution: {integrity: sha512-d0FdzYIiAePqRJEb90WlJDkjUEx42xhivxN8muUBmfZnP+tzUgz12DJ2hRJi8sIHCME7jeK1PTMgKPSfTd8JrA==} engines: {node: '>=16'} - synckit@0.8.8: - resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} + synckit@0.9.1: + resolution: {integrity: sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==} engines: {node: ^14.18.0 || >=16.0.0} - tailwindcss@3.4.4: - resolution: {integrity: sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==} + tailwindcss@3.4.6: + resolution: {integrity: sha512-1uRHzPB+Vzu57ocybfZ4jh5Q3SdlH7XW23J5sQoM9LhE9eIOlzxer/3XPSsycvih3rboRsvt0QCmzSrqyOYUIA==} engines: {node: '>=14.0.0'} hasBin: true - tar-fs@3.0.5: - resolution: {integrity: sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==} + tar-fs@3.0.6: + resolution: {integrity: sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==} tar-stream@3.1.7: resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} @@ -2590,8 +2823,13 @@ packages: engines: {node: '>=10'} hasBin: true - text-decoder@1.1.0: - resolution: {integrity: sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==} + terser@5.31.3: + resolution: {integrity: sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==} + engines: {node: '>=10'} + hasBin: true + + text-decoder@1.1.1: + resolution: {integrity: sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==} text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -2612,18 +2850,26 @@ packages: tinybench@2.8.0: resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==} - tinypool@0.8.4: - resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} + tinypool@1.0.0: + resolution: {integrity: sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@1.2.0: + resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} engines: {node: '>=14.0.0'} - tinyspy@2.2.1: - resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} + tinyspy@3.0.0: + resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==} engines: {node: '>=14.0.0'} to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} @@ -2648,16 +2894,19 @@ packages: tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + tweetnacl@1.0.3: + resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} - typescript-eslint@7.13.1: - resolution: {integrity: sha512-pvLEuRs8iS9s3Cnp/Wt//hpK8nKc8hVa3cLljHqzaJJQYP8oys8GUyIFqtlev+2lT/fqMPcyQko+HJ6iYK3nFA==} + typescript-eslint@7.16.1: + resolution: {integrity: sha512-889oE5qELj65q/tGeOSvlreNKhimitFwZqQ0o7PcWC7/lgRkAMknznsCsV8J8mZGTP/Z+cIbX8accf2DE33hrA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -2666,14 +2915,11 @@ packages: typescript: optional: true - typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + typescript@5.5.3: + resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==} engines: {node: '>=14.17'} hasBin: true - ufo@1.5.3: - resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} - uid@2.0.2: resolution: {integrity: sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==} engines: {node: '>=8'} @@ -2688,6 +2934,10 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + update-browserslist-db@1.0.16: resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} hasBin: true @@ -2703,13 +2953,21 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - vite-node@1.6.0: - resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vite-node@2.0.3: + resolution: {integrity: sha512-14jzwMx7XTcMB+9BhGQyoEAmSl0eOr3nrnn+Z12WNERtOvLN+d2scbRUvyni05rT3997Bg+rZb47NyP4IQPKXg==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true - vite@5.3.1: - resolution: {integrity: sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==} + vite@5.3.4: + resolution: {integrity: sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -2744,15 +3002,15 @@ packages: vite: optional: true - vitest@1.6.0: - resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} + vitest@2.0.3: + resolution: {integrity: sha512-o3HRvU93q6qZK4rI2JrhKyZMMuxg/JRt30E6qeQs6ueaiz5hr1cPj+Sk2kATgQzMMqsa2DiNI0TIK++1ULx8Jw==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 1.6.0 - '@vitest/ui': 1.6.0 + '@vitest/browser': 2.0.3 + '@vitest/ui': 2.0.3 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -2774,8 +3032,8 @@ packages: engines: {node: '>= 8'} hasBin: true - why-is-node-running@2.2.2: - resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} engines: {node: '>=8'} hasBin: true @@ -2798,8 +3056,8 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@8.17.1: - resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -2814,9 +3072,6 @@ packages: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - yaml@1.10.2: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} @@ -2841,10 +3096,6 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - yocto-queue@1.0.0: - resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} - engines: {node: '>=12.20'} - zip-stream@6.0.1: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} engines: {node: '>= 14'} @@ -2957,14 +3208,14 @@ snapshots: '@esbuild/win32-x64@0.21.5': optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@9.5.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@9.7.0)': dependencies: - eslint: 9.5.0 + eslint: 9.7.0 eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.10.0': {} + '@eslint-community/regexpp@4.11.0': {} - '@eslint/config-array@0.16.0': + '@eslint/config-array@0.17.0': dependencies: '@eslint/object-schema': 2.1.4 debug: 4.3.5 @@ -2986,30 +3237,30 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.5.0': {} + '@eslint/js@9.7.0': {} '@eslint/object-schema@2.1.4': {} - '@holochain/client@0.17.0': + '@holochain/client@0.18.0-dev.6': dependencies: '@bitgo/blake2b': 3.2.4 '@holochain/serialization': 0.1.0-beta-rc.3 '@msgpack/msgpack': 2.8.0 emittery: 1.0.3 - isomorphic-ws: 5.0.0(ws@8.17.1) + isomorphic-ws: 5.0.0(ws@8.18.0) js-base64: 3.7.7 libsodium-wrappers: 0.7.13 lodash-es: 4.17.21 - ws: 8.17.1 + ws: 8.18.0 transitivePeerDependencies: - bufferutil - utf-8-validate - '@holochain/hc-seed-bundle@0.1.1(typescript@5.4.5)': + '@holochain/hc-seed-bundle@0.1.1(typescript@5.5.3)': dependencies: '@msgpack/msgpack': 3.0.0-beta2 libsodium-wrappers-sumo: 0.7.13 - typescript: 5.4.5 + typescript: 5.5.3 '@holochain/serialization@0.1.0-beta-rc.3': {} @@ -3026,14 +3277,10 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 - '@jest/schemas@29.6.3': - dependencies: - '@sinclair/typebox': 0.27.8 - '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 '@jridgewell/resolve-uri@3.1.2': {} @@ -3047,10 +3294,12 @@ snapshots: '@jridgewell/sourcemap-codec@1.4.15': {} + '@jridgewell/sourcemap-codec@1.5.0': {} + '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 '@lukeed/csprng@1.1.0': {} @@ -3077,134 +3326,132 @@ snapshots: '@polka/url@1.0.0-next.25': {} - '@puppeteer/browsers@2.2.3': + '@puppeteer/browsers@2.2.4': dependencies: - debug: 4.3.4 + debug: 4.3.5 extract-zip: 2.0.1 progress: 2.0.3 proxy-agent: 6.4.0 - semver: 7.6.0 - tar-fs: 3.0.5 + semver: 7.6.3 + tar-fs: 3.0.6 unbzip2-stream: 1.4.3 yargs: 17.7.2 transitivePeerDependencies: - supports-color - '@rollup/plugin-commonjs@26.0.1(rollup@4.18.0)': + '@rollup/plugin-commonjs@26.0.1(rollup@4.18.1)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.18.0) + '@rollup/pluginutils': 5.1.0(rollup@4.18.1) commondir: 1.0.1 estree-walker: 2.0.2 glob: 10.4.2 is-reference: 1.2.1 magic-string: 0.30.10 optionalDependencies: - rollup: 4.18.0 + rollup: 4.18.1 - '@rollup/plugin-inject@5.0.5(rollup@4.18.0)': + '@rollup/plugin-inject@5.0.5(rollup@4.18.1)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.18.0) + '@rollup/pluginutils': 5.1.0(rollup@4.18.1) estree-walker: 2.0.2 magic-string: 0.30.10 optionalDependencies: - rollup: 4.18.0 + rollup: 4.18.1 - '@rollup/plugin-node-resolve@15.2.3(rollup@4.18.0)': + '@rollup/plugin-node-resolve@15.2.3(rollup@4.18.1)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.18.0) + '@rollup/pluginutils': 5.1.0(rollup@4.18.1) '@types/resolve': 1.20.2 deepmerge: 4.3.1 is-builtin-module: 3.2.1 is-module: 1.0.0 resolve: 1.22.8 optionalDependencies: - rollup: 4.18.0 + rollup: 4.18.1 - '@rollup/plugin-replace@5.0.7(rollup@4.18.0)': + '@rollup/plugin-replace@5.0.7(rollup@4.18.1)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.18.0) + '@rollup/pluginutils': 5.1.0(rollup@4.18.1) magic-string: 0.30.10 optionalDependencies: - rollup: 4.18.0 + rollup: 4.18.1 - '@rollup/plugin-terser@0.4.4(rollup@4.18.0)': + '@rollup/plugin-terser@0.4.4(rollup@4.18.1)': dependencies: serialize-javascript: 6.0.2 smob: 1.5.0 terser: 5.31.0 optionalDependencies: - rollup: 4.18.0 + rollup: 4.18.1 '@rollup/pluginutils@4.2.1': dependencies: estree-walker: 2.0.2 picomatch: 2.3.1 - '@rollup/pluginutils@5.1.0(rollup@4.18.0)': + '@rollup/pluginutils@5.1.0(rollup@4.18.1)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.18.0 + rollup: 4.18.1 - '@rollup/rollup-android-arm-eabi@4.18.0': + '@rollup/rollup-android-arm-eabi@4.18.1': optional: true - '@rollup/rollup-android-arm64@4.18.0': + '@rollup/rollup-android-arm64@4.18.1': optional: true - '@rollup/rollup-darwin-arm64@4.18.0': + '@rollup/rollup-darwin-arm64@4.18.1': optional: true - '@rollup/rollup-darwin-x64@4.18.0': + '@rollup/rollup-darwin-x64@4.18.1': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.18.0': + '@rollup/rollup-linux-arm-gnueabihf@4.18.1': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.18.0': + '@rollup/rollup-linux-arm-musleabihf@4.18.1': optional: true - '@rollup/rollup-linux-arm64-gnu@4.18.0': + '@rollup/rollup-linux-arm64-gnu@4.18.1': optional: true - '@rollup/rollup-linux-arm64-musl@4.18.0': + '@rollup/rollup-linux-arm64-musl@4.18.1': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': + '@rollup/rollup-linux-powerpc64le-gnu@4.18.1': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.18.0': + '@rollup/rollup-linux-riscv64-gnu@4.18.1': optional: true - '@rollup/rollup-linux-s390x-gnu@4.18.0': + '@rollup/rollup-linux-s390x-gnu@4.18.1': optional: true - '@rollup/rollup-linux-x64-gnu@4.18.0': + '@rollup/rollup-linux-x64-gnu@4.18.1': optional: true - '@rollup/rollup-linux-x64-musl@4.18.0': + '@rollup/rollup-linux-x64-musl@4.18.1': optional: true - '@rollup/rollup-win32-arm64-msvc@4.18.0': + '@rollup/rollup-win32-arm64-msvc@4.18.1': optional: true - '@rollup/rollup-win32-ia32-msvc@4.18.0': + '@rollup/rollup-win32-ia32-msvc@4.18.1': optional: true - '@rollup/rollup-win32-x64-msvc@4.18.0': + '@rollup/rollup-win32-x64-msvc@4.18.1': optional: true - '@sinclair/typebox@0.27.8': {} - - '@sveltejs/adapter-static@3.0.2(@sveltejs/kit@2.5.17(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)))(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)))': + '@sveltejs/adapter-static@3.0.2(@sveltejs/kit@2.5.18(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)))(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)))': dependencies: - '@sveltejs/kit': 2.5.17(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)))(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)) + '@sveltejs/kit': 2.5.18(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)))(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)) - '@sveltejs/kit@2.5.17(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)))(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0))': + '@sveltejs/kit@2.5.18(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)))(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)) + '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.0.0 @@ -3218,49 +3465,72 @@ snapshots: sirv: 2.0.4 svelte: 4.2.18 tiny-glob: 0.2.9 - vite: 5.3.1(@types/node@20.14.8)(terser@5.31.0) + vite: 5.3.4(@types/node@20.14.11)(terser@5.31.3) - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)))(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0))': + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)))(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)) + '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)) debug: 4.3.4 svelte: 4.2.18 - vite: 5.3.1(@types/node@20.14.8)(terser@5.31.0) + vite: 5.3.4(@types/node@20.14.11)(terser@5.31.3) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0))': + '@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)))(svelte@4.2.18)(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)) + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)))(svelte@4.2.18)(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)) debug: 4.3.4 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.10 svelte: 4.2.18 svelte-hmr: 0.16.0(svelte@4.2.18) - vite: 5.3.1(@types/node@20.14.8)(terser@5.31.0) - vitefu: 0.2.5(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)) + vite: 5.3.4(@types/node@20.14.11)(terser@5.31.3) + vitefu: 0.2.5(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)) transitivePeerDependencies: - supports-color - '@tanstack/query-core@5.45.0': {} + '@tanstack/query-core@5.51.5': {} - '@tanstack/svelte-query@5.46.1(svelte@4.2.18)': + '@tanstack/svelte-query@5.51.5(svelte@4.2.18)': dependencies: - '@tanstack/query-core': 5.45.0 + '@tanstack/query-core': 5.51.5 svelte: 4.2.18 '@tootallnate/quickjs-emscripten@0.23.0': {} + '@types/body-parser@1.19.5': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 20.14.8 + '@types/chrome@0.0.268': dependencies: '@types/filesystem': 0.0.36 '@types/har-format': 1.2.15 + '@types/connect@3.4.38': + dependencies: + '@types/node': 20.14.8 + '@types/cookie@0.6.0': {} '@types/estree@1.0.5': {} + '@types/express-serve-static-core@4.19.5': + dependencies: + '@types/node': 20.14.8 + '@types/qs': 6.9.15 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + + '@types/express@4.17.21': + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 4.19.5 + '@types/qs': 6.9.15 + '@types/serve-static': 1.15.7 + '@types/file-saver@2.0.7': {} '@types/filesystem@0.0.36': @@ -3271,160 +3541,184 @@ snapshots: '@types/har-format@1.2.15': {} - '@types/node@20.14.8': + '@types/http-errors@2.0.4': {} + + '@types/mime@1.3.5': {} + + '@types/node@20.14.11': dependencies: undici-types: 5.26.5 optional: true + '@types/node@20.14.8': + dependencies: + undici-types: 5.26.5 + '@types/pug@2.0.10': {} + '@types/qs@6.9.15': {} + + '@types/range-parser@1.2.7': {} + '@types/resolve@1.20.2': {} - '@types/yauzl@2.10.3': + '@types/send@0.17.4': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 20.14.8 + + '@types/serve-static@1.15.7': dependencies: + '@types/http-errors': 2.0.4 '@types/node': 20.14.8 + '@types/send': 0.17.4 + + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 20.14.11 optional: true - '@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@7.16.1(@typescript-eslint/parser@7.16.1(eslint@9.7.0)(typescript@5.5.3))(eslint@9.7.0)(typescript@5.5.3)': dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.13.1(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.13.1 - '@typescript-eslint/type-utils': 7.13.1(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.13.1(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.13.1 - eslint: 9.5.0 + '@eslint-community/regexpp': 4.11.0 + '@typescript-eslint/parser': 7.16.1(eslint@9.7.0)(typescript@5.5.3) + '@typescript-eslint/scope-manager': 7.16.1 + '@typescript-eslint/type-utils': 7.16.1(eslint@9.7.0)(typescript@5.5.3) + '@typescript-eslint/utils': 7.16.1(eslint@9.7.0)(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.16.1 + eslint: 9.7.0 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/parser@7.16.1(eslint@9.7.0)(typescript@5.5.3)': dependencies: - '@typescript-eslint/scope-manager': 7.13.1 - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.13.1 - debug: 4.3.4 - eslint: 9.5.0 + '@typescript-eslint/scope-manager': 7.16.1 + '@typescript-eslint/types': 7.16.1 + '@typescript-eslint/typescript-estree': 7.16.1(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.16.1 + debug: 4.3.5 + eslint: 9.7.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@7.13.1': + '@typescript-eslint/scope-manager@7.16.1': dependencies: - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/visitor-keys': 7.13.1 + '@typescript-eslint/types': 7.16.1 + '@typescript-eslint/visitor-keys': 7.16.1 - '@typescript-eslint/type-utils@7.13.1(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/type-utils@7.16.1(eslint@9.7.0)(typescript@5.5.3)': dependencies: - '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.4.5) - '@typescript-eslint/utils': 7.13.1(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 7.16.1(typescript@5.5.3) + '@typescript-eslint/utils': 7.16.1(eslint@9.7.0)(typescript@5.5.3) debug: 4.3.5 - eslint: 9.5.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + eslint: 9.7.0 + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@7.13.1': {} + '@typescript-eslint/types@7.16.1': {} - '@typescript-eslint/typescript-estree@7.13.1(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@7.16.1(typescript@5.5.3)': dependencies: - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/visitor-keys': 7.13.1 - debug: 4.3.4 + '@typescript-eslint/types': 7.16.1 + '@typescript-eslint/visitor-keys': 7.16.1 + debug: 4.3.5 globby: 11.1.0 is-glob: 4.0.3 - minimatch: 9.0.4 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.4.5) + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@7.13.1(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/utils@7.16.1(eslint@9.7.0)(typescript@5.5.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) - '@typescript-eslint/scope-manager': 7.13.1 - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.4.5) - eslint: 9.5.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.7.0) + '@typescript-eslint/scope-manager': 7.16.1 + '@typescript-eslint/types': 7.16.1 + '@typescript-eslint/typescript-estree': 7.16.1(typescript@5.5.3) + eslint: 9.7.0 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/visitor-keys@7.13.1': + '@typescript-eslint/visitor-keys@7.16.1': dependencies: - '@typescript-eslint/types': 7.13.1 + '@typescript-eslint/types': 7.16.1 eslint-visitor-keys: 3.4.3 - '@vitest/expect@1.6.0': + '@vitest/expect@2.0.3': + dependencies: + '@vitest/spy': 2.0.3 + '@vitest/utils': 2.0.3 + chai: 5.1.1 + tinyrainbow: 1.2.0 + + '@vitest/pretty-format@2.0.3': dependencies: - '@vitest/spy': 1.6.0 - '@vitest/utils': 1.6.0 - chai: 4.4.1 + tinyrainbow: 1.2.0 - '@vitest/runner@1.6.0': + '@vitest/runner@2.0.3': dependencies: - '@vitest/utils': 1.6.0 - p-limit: 5.0.0 + '@vitest/utils': 2.0.3 pathe: 1.1.2 - '@vitest/snapshot@1.6.0': + '@vitest/snapshot@2.0.3': dependencies: + '@vitest/pretty-format': 2.0.3 magic-string: 0.30.10 pathe: 1.1.2 - pretty-format: 29.7.0 - '@vitest/spy@1.6.0': + '@vitest/spy@2.0.3': dependencies: - tinyspy: 2.2.1 + tinyspy: 3.0.0 - '@vitest/ui@1.6.0(vitest@1.6.0)': + '@vitest/ui@2.0.3(vitest@2.0.3)': dependencies: - '@vitest/utils': 1.6.0 + '@vitest/utils': 2.0.3 fast-glob: 3.3.2 fflate: 0.8.2 flatted: 3.3.1 pathe: 1.1.2 - picocolors: 1.0.1 sirv: 2.0.4 - vitest: 1.6.0(@types/node@20.14.8)(@vitest/ui@1.6.0)(terser@5.31.0) + tinyrainbow: 1.2.0 + vitest: 2.0.3(@types/node@20.14.11)(@vitest/ui@2.0.3)(terser@5.31.3) - '@vitest/utils@1.6.0': + '@vitest/utils@2.0.3': dependencies: - diff-sequences: 29.6.3 + '@vitest/pretty-format': 2.0.3 estree-walker: 3.0.3 - loupe: 2.3.7 - pretty-format: 29.7.0 + loupe: 3.1.1 + tinyrainbow: 1.2.0 abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 - acorn-jsx@5.3.2(acorn@8.11.3): + accepts@1.3.8: dependencies: - acorn: 8.11.3 + mime-types: 2.1.35 + negotiator: 0.6.3 - acorn-jsx@5.3.2(acorn@8.12.0): + acorn-jsx@5.3.2(acorn@8.12.1): dependencies: - acorn: 8.12.0 - - acorn-walk@8.3.3: - dependencies: - acorn: 8.12.0 + acorn: 8.12.1 acorn@8.11.3: {} - acorn@8.12.0: {} + acorn@8.12.1: {} agent-base@7.1.1: dependencies: @@ -3453,8 +3747,6 @@ snapshots: dependencies: color-convert: 2.0.1 - ansi-styles@5.2.0: {} - ansi-styles@6.2.1: {} any-promise@1.3.0: {} @@ -3492,9 +3784,11 @@ snapshots: dependencies: dequal: 2.0.3 + array-flatten@1.1.1: {} + array-union@2.1.0: {} - assertion-error@1.1.0: {} + assertion-error@2.0.1: {} ast-types@0.13.4: dependencies: @@ -3502,14 +3796,14 @@ snapshots: async@3.2.5: {} - autoprefixer@10.4.19(postcss@8.4.38): + autoprefixer@10.4.19(postcss@8.4.39): dependencies: browserslist: 4.23.0 caniuse-lite: 1.0.30001620 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.0.1 - postcss: 8.4.38 + postcss: 8.4.39 postcss-value-parser: 4.2.0 axobject-query@4.0.0: @@ -3551,6 +3845,23 @@ snapshots: blakejs@1.2.1: {} + body-parser@1.20.2: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -3589,23 +3900,31 @@ snapshots: builtin-modules@3.3.0: {} + bytes@3.1.2: {} + cac@6.7.14: {} + call-bind@1.0.7: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + callsites@3.1.0: {} camelcase-css@2.0.1: {} caniuse-lite@1.0.30001620: {} - chai@4.4.1: + chai@5.1.1: dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.4 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.0.8 + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.1 + pathval: 2.0.0 chalk@2.4.2: dependencies: @@ -3620,9 +3939,7 @@ snapshots: chalk@5.3.0: {} - check-error@1.0.3: - dependencies: - get-func-name: 2.0.2 + check-error@2.1.1: {} chokidar@3.6.0: dependencies: @@ -3636,7 +3953,7 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - chromium-bidi@0.5.24(devtools-protocol@0.0.1299070): + chromium-bidi@0.6.1(devtools-protocol@0.0.1299070): dependencies: devtools-protocol: 0.0.1299070 mitt: 3.0.1 @@ -3714,20 +4031,26 @@ snapshots: tree-kill: 1.2.2 yargs: 17.7.2 - confbox@0.1.7: {} + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + cookie-signature@1.0.6: {} cookie@0.6.0: {} core-util-is@1.0.3: {} - cosmiconfig@9.0.0(typescript@5.4.5): + cosmiconfig@9.0.0(typescript@5.5.3): dependencies: env-paths: 2.2.1 import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 crc-32@1.2.2: {} @@ -3755,6 +4078,10 @@ snapshots: dependencies: '@babel/runtime': 7.24.5 + debug@2.6.9: + dependencies: + ms: 2.0.0 + debug@4.3.4: dependencies: ms: 2.1.2 @@ -3763,22 +4090,30 @@ snapshots: dependencies: ms: 2.1.2 - deep-eql@4.1.4: - dependencies: - type-detect: 4.0.8 + deep-eql@5.0.2: {} deep-is@0.1.4: {} deepmerge@4.3.1: {} + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + degenerator@5.0.1: dependencies: ast-types: 0.13.4 escodegen: 2.1.0 esprima: 4.0.1 + depd@2.0.0: {} + dequal@2.0.3: {} + destroy@1.2.0: {} + detect-indent@6.1.0: {} devalue@5.0.0: {} @@ -3787,8 +4122,6 @@ snapshots: didyoumean@1.2.2: {} - diff-sequences@29.6.3: {} - dir-glob@3.0.1: dependencies: path-type: 4.0.0 @@ -3799,6 +4132,8 @@ snapshots: eastasianwidth@0.2.0: {} + ee-first@1.1.1: {} + electron-to-chromium@1.4.776: {} emittery@1.0.3: {} @@ -3809,6 +4144,8 @@ snapshots: emoji-regex@9.2.2: {} + encodeurl@1.0.2: {} + end-of-stream@1.4.4: dependencies: once: 1.4.0 @@ -3819,6 +4156,12 @@ snapshots: dependencies: is-arrayish: 0.2.1 + es-define-property@1.0.0: + dependencies: + get-intrinsic: 1.2.4 + + es-errors@1.3.0: {} + es6-promise@3.3.1: {} esbuild@0.21.5: @@ -3849,6 +4192,8 @@ snapshots: escalade@3.1.2: {} + escape-html@1.0.3: {} + escape-string-regexp@1.0.5: {} escape-string-regexp@4.0.0: {} @@ -3861,42 +4206,42 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-compat-utils@0.5.1(eslint@9.5.0): + eslint-compat-utils@0.5.1(eslint@9.7.0): dependencies: - eslint: 9.5.0 + eslint: 9.7.0 semver: 7.6.2 - eslint-config-prettier@9.1.0(eslint@9.5.0): + eslint-config-prettier@9.1.0(eslint@9.7.0): dependencies: - eslint: 9.5.0 + eslint: 9.7.0 - eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0(eslint@9.5.0))(eslint@9.5.0)(prettier@3.3.2): + eslint-plugin-prettier@5.2.1(eslint-config-prettier@9.1.0(eslint@9.7.0))(eslint@9.7.0)(prettier@3.3.3): dependencies: - eslint: 9.5.0 - prettier: 3.3.2 + eslint: 9.7.0 + prettier: 3.3.3 prettier-linter-helpers: 1.0.0 - synckit: 0.8.8 + synckit: 0.9.1 optionalDependencies: - eslint-config-prettier: 9.1.0(eslint@9.5.0) + eslint-config-prettier: 9.1.0(eslint@9.7.0) - eslint-plugin-simple-import-sort@12.1.0(eslint@9.5.0): + eslint-plugin-simple-import-sort@12.1.1(eslint@9.7.0): dependencies: - eslint: 9.5.0 + eslint: 9.7.0 - eslint-plugin-svelte@2.40.0(eslint@9.5.0)(svelte@4.2.18): + eslint-plugin-svelte@2.42.0(eslint@9.7.0)(svelte@4.2.18): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) - '@jridgewell/sourcemap-codec': 1.4.15 - eslint: 9.5.0 - eslint-compat-utils: 0.5.1(eslint@9.5.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.7.0) + '@jridgewell/sourcemap-codec': 1.5.0 + eslint: 9.7.0 + eslint-compat-utils: 0.5.1(eslint@9.7.0) esutils: 2.0.3 - known-css-properties: 0.32.0 - postcss: 8.4.38 - postcss-load-config: 3.1.4(postcss@8.4.38) - postcss-safe-parser: 6.0.0(postcss@8.4.38) - postcss-selector-parser: 6.1.0 + known-css-properties: 0.34.0 + postcss: 8.4.39 + postcss-load-config: 3.1.4(postcss@8.4.39) + postcss-safe-parser: 6.0.0(postcss@8.4.39) + postcss-selector-parser: 6.1.1 semver: 7.6.2 - svelte-eslint-parser: 0.39.1(svelte@4.2.18) + svelte-eslint-parser: 0.40.0(svelte@4.2.18) optionalDependencies: svelte: 4.2.18 transitivePeerDependencies: @@ -3907,7 +4252,7 @@ snapshots: esrecurse: 4.3.0 estraverse: 5.3.0 - eslint-scope@8.0.1: + eslint-scope@8.0.2: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 @@ -3916,25 +4261,25 @@ snapshots: eslint-visitor-keys@4.0.0: {} - eslint@9.5.0: + eslint@9.7.0: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/config-array': 0.16.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.7.0) + '@eslint-community/regexpp': 4.11.0 + '@eslint/config-array': 0.17.0 '@eslint/eslintrc': 3.1.0 - '@eslint/js': 9.5.0 + '@eslint/js': 9.7.0 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.3.0 '@nodelib/fs.walk': 1.2.8 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4 + debug: 4.3.5 escape-string-regexp: 4.0.0 - eslint-scope: 8.0.1 + eslint-scope: 8.0.2 eslint-visitor-keys: 4.0.0 espree: 10.1.0 - esquery: 1.5.0 + esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 8.0.0 @@ -3959,19 +4304,19 @@ snapshots: espree@10.1.0: dependencies: - acorn: 8.12.0 - acorn-jsx: 5.3.2(acorn@8.12.0) + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) eslint-visitor-keys: 4.0.0 espree@9.6.1: dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) eslint-visitor-keys: 3.4.3 esprima@4.0.1: {} - esquery@1.5.0: + esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -3991,6 +4336,8 @@ snapshots: esutils@2.0.3: {} + etag@1.8.1: {} + event-target-shim@5.0.1: {} eventemitter3@5.0.1: {} @@ -4009,6 +4356,42 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 + express@4.19.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.2 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.6.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.11.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + extract-zip@2.0.1: dependencies: debug: 4.3.5 @@ -4061,6 +4444,18 @@ snapshots: dependencies: to-regex-range: 5.0.1 + finalhandler@1.2.0: + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + find-cache-dir@3.3.2: dependencies: commondir: 1.0.1 @@ -4089,8 +4484,12 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 + forwarded@0.2.0: {} + fraction.js@4.3.7: {} + fresh@0.5.2: {} + fs-extra@10.1.0: dependencies: graceful-fs: 4.2.11 @@ -4116,6 +4515,14 @@ snapshots: get-func-name@2.0.2: {} + get-intrinsic@1.2.4: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + get-stream@5.2.0: dependencies: pump: 3.0.0 @@ -4143,7 +4550,7 @@ snapshots: dependencies: foreground-child: 3.1.1 jackspeak: 2.3.6 - minimatch: 9.0.4 + minimatch: 9.0.5 minipass: 7.1.1 path-scurry: 1.11.1 @@ -4167,7 +4574,7 @@ snapshots: globals@14.0.0: {} - globals@15.6.0: {} + globals@15.8.0: {} globalyzer@0.1.0: {} @@ -4182,6 +4589,10 @@ snapshots: globrex@0.1.2: {} + gopd@1.0.1: + dependencies: + get-intrinsic: 1.2.4 + graceful-fs@4.2.11: {} graphemer@1.4.0: {} @@ -4190,10 +4601,26 @@ snapshots: has-flag@4.0.0: {} + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.0 + + has-proto@1.0.3: {} + + has-symbols@1.0.3: {} + hasown@2.0.2: dependencies: function-bind: 1.1.2 + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.1 @@ -4201,7 +4628,7 @@ snapshots: transitivePeerDependencies: - supports-color - https-proxy-agent@7.0.4: + https-proxy-agent@7.0.5: dependencies: agent-base: 7.1.1 debug: 4.3.5 @@ -4210,7 +4637,11 @@ snapshots: human-signals@5.0.0: {} - husky@9.0.11: {} + husky@9.1.0: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 ieee754@1.2.1: {} @@ -4239,6 +4670,8 @@ snapshots: jsbn: 1.1.0 sprintf-js: 1.1.3 + ipaddr.js@1.9.1: {} + is-arrayish@0.2.1: {} is-binary-path@2.1.0: @@ -4289,9 +4722,9 @@ snapshots: isexe@2.0.0: {} - isomorphic-ws@5.0.0(ws@8.17.1): + isomorphic-ws@5.0.0(ws@8.18.0): dependencies: - ws: 8.17.1 + ws: 8.18.0 jackspeak@2.3.6: dependencies: @@ -4311,8 +4744,6 @@ snapshots: js-tokens@4.0.0: {} - js-tokens@9.0.0: {} - js-yaml@4.1.0: dependencies: argparse: 2.0.1 @@ -4346,7 +4777,7 @@ snapshots: kleur@4.1.5: {} - known-css-properties@0.32.0: {} + known-css-properties@0.34.0: {} lazystream@1.0.1: dependencies: @@ -4377,6 +4808,9 @@ snapshots: lilconfig@3.1.1: {} + lilconfig@3.1.2: + optional: true + lines-and-columns@1.2.4: {} lint-staged@15.2.7: @@ -4403,11 +4837,6 @@ snapshots: rfdc: 1.3.1 wrap-ansi: 9.0.0 - local-pkg@0.5.0: - dependencies: - mlly: 1.7.1 - pkg-types: 1.1.1 - locate-character@3.0.0: {} locate-path@5.0.0: @@ -4432,16 +4861,12 @@ snapshots: strip-ansi: 7.1.0 wrap-ansi: 9.0.0 - loupe@2.3.7: + loupe@3.1.1: dependencies: get-func-name: 2.0.2 lru-cache@10.2.2: {} - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - lru-cache@7.18.3: {} magic-string@0.25.9: @@ -4450,7 +4875,7 @@ snapshots: magic-string@0.30.10: dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 make-dir@3.1.0: dependencies: @@ -4458,10 +4883,16 @@ snapshots: mdn-data@2.0.30: {} + media-typer@0.3.0: {} + + merge-descriptors@1.0.1: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} + methods@1.1.2: {} + micromatch@4.0.6: dependencies: braces: 3.0.3 @@ -4472,6 +4903,14 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + mimic-fn@2.1.0: {} mimic-fn@4.0.0: {} @@ -4490,6 +4929,10 @@ snapshots: dependencies: brace-expansion: 2.0.1 + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + minimist@1.2.8: {} minipass@7.1.1: {} @@ -4502,19 +4945,16 @@ snapshots: dependencies: minimist: 1.2.8 - mlly@1.7.1: - dependencies: - acorn: 8.12.0 - pathe: 1.1.2 - pkg-types: 1.1.1 - ufo: 1.5.3 - mri@1.2.0: {} mrmime@2.0.0: {} + ms@2.0.0: {} + ms@2.1.2: {} + ms@2.1.3: {} + mylas@2.1.13: {} mz@2.7.0: @@ -4531,6 +4971,8 @@ snapshots: natural-compare@1.4.0: {} + negotiator@0.6.3: {} + netmask@2.0.2: {} node-releases@2.0.14: {} @@ -4547,6 +4989,12 @@ snapshots: object-hash@3.0.0: {} + object-inspect@1.13.2: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -4576,10 +5024,6 @@ snapshots: dependencies: yocto-queue: 0.1.0 - p-limit@5.0.0: - dependencies: - yocto-queue: 1.0.0 - p-locate@4.1.0: dependencies: p-limit: 2.3.0 @@ -4590,16 +5034,16 @@ snapshots: p-try@2.2.0: {} - pac-proxy-agent@7.0.1: + pac-proxy-agent@7.0.2: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.1 debug: 4.3.5 get-uri: 6.0.3 http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.4 + https-proxy-agent: 7.0.5 pac-resolver: 7.0.1 - socks-proxy-agent: 8.0.3 + socks-proxy-agent: 8.0.4 transitivePeerDependencies: - supports-color @@ -4623,6 +5067,8 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + parseurl@1.3.3: {} + path-exists@4.0.0: {} path-is-absolute@1.0.1: {} @@ -4638,11 +5084,13 @@ snapshots: lru-cache: 10.2.2 minipass: 7.1.1 + path-to-regexp@0.1.7: {} + path-type@4.0.0: {} pathe@1.1.2: {} - pathval@1.1.1: {} + pathval@2.0.0: {} pend@1.2.0: {} @@ -4668,68 +5116,69 @@ snapshots: dependencies: find-up: 4.1.0 - pkg-types@1.1.1: - dependencies: - confbox: 0.1.7 - mlly: 1.7.1 - pathe: 1.1.2 - plimit-lit@1.6.1: dependencies: queue-lit: 1.5.2 - postcss-import@15.1.0(postcss@8.4.38): + postcss-import@15.1.0(postcss@8.4.39): dependencies: - postcss: 8.4.38 + postcss: 8.4.39 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.8 - postcss-js@4.0.1(postcss@8.4.38): + postcss-js@4.0.1(postcss@8.4.39): dependencies: camelcase-css: 2.0.1 - postcss: 8.4.38 + postcss: 8.4.39 - postcss-load-config@3.1.4(postcss@8.4.38): + postcss-load-config@3.1.4(postcss@8.4.39): dependencies: lilconfig: 2.1.0 yaml: 1.10.2 optionalDependencies: - postcss: 8.4.38 + postcss: 8.4.39 - postcss-load-config@4.0.2(postcss@8.4.38): + postcss-load-config@4.0.2(postcss@8.4.39): dependencies: lilconfig: 3.1.1 yaml: 2.4.2 optionalDependencies: - postcss: 8.4.38 + postcss: 8.4.39 + + postcss-load-config@6.0.1(postcss@8.4.39): + dependencies: + lilconfig: 3.1.2 + optionalDependencies: + postcss: 8.4.39 + optional: true - postcss-nested@6.0.1(postcss@8.4.38): + postcss-nested@6.0.1(postcss@8.4.39): dependencies: - postcss: 8.4.38 + postcss: 8.4.39 postcss-selector-parser: 6.0.16 - postcss-safe-parser@6.0.0(postcss@8.4.38): + postcss-safe-parser@6.0.0(postcss@8.4.39): dependencies: - postcss: 8.4.38 + postcss: 8.4.39 - postcss-scss@4.0.9(postcss@8.4.38): + postcss-scss@4.0.9(postcss@8.4.39): dependencies: - postcss: 8.4.38 + postcss: 8.4.39 postcss-selector-parser@6.0.16: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss-selector-parser@6.1.0: + postcss-selector-parser@6.1.1: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 postcss-value-parser@4.2.0: {} - postcss@8.4.38: + postcss@8.4.39: dependencies: nanoid: 3.3.7 picocolors: 1.0.1 @@ -4741,24 +5190,18 @@ snapshots: dependencies: fast-diff: 1.3.0 - prettier-plugin-svelte@3.2.5(prettier@3.3.2)(svelte@4.2.18): + prettier-plugin-svelte@3.2.6(prettier@3.3.3)(svelte@4.2.18): dependencies: - prettier: 3.3.2 + prettier: 3.3.3 svelte: 4.2.18 - prettier-plugin-tailwindcss@0.6.5(prettier-plugin-svelte@3.2.5(prettier@3.3.2)(svelte@4.2.18))(prettier@3.3.2): + prettier-plugin-tailwindcss@0.6.5(prettier-plugin-svelte@3.2.6(prettier@3.3.3)(svelte@4.2.18))(prettier@3.3.3): dependencies: - prettier: 3.3.2 + prettier: 3.3.3 optionalDependencies: - prettier-plugin-svelte: 3.2.5(prettier@3.3.2)(svelte@4.2.18) - - prettier@3.3.2: {} + prettier-plugin-svelte: 3.2.6(prettier@3.3.3)(svelte@4.2.18) - pretty-format@29.7.0: - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 + prettier@3.3.3: {} process-nextick-args@2.0.1: {} @@ -4766,16 +5209,21 @@ snapshots: progress@2.0.3: {} + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + proxy-agent@6.4.0: dependencies: agent-base: 7.1.1 debug: 4.3.5 http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.4 + https-proxy-agent: 7.0.5 lru-cache: 7.18.3 - pac-proxy-agent: 7.0.1 + pac-proxy-agent: 7.0.2 proxy-from-env: 1.1.0 - socks-proxy-agent: 8.0.3 + socks-proxy-agent: 8.0.4 transitivePeerDependencies: - supports-color @@ -4788,30 +5236,34 @@ snapshots: punycode@2.3.1: {} - puppeteer-core@22.12.0: + puppeteer-core@22.13.1: dependencies: - '@puppeteer/browsers': 2.2.3 - chromium-bidi: 0.5.24(devtools-protocol@0.0.1299070) + '@puppeteer/browsers': 2.2.4 + chromium-bidi: 0.6.1(devtools-protocol@0.0.1299070) debug: 4.3.5 devtools-protocol: 0.0.1299070 - ws: 8.17.1 + ws: 8.18.0 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - puppeteer@22.12.0(typescript@5.4.5): + puppeteer@22.13.1(typescript@5.5.3): dependencies: - '@puppeteer/browsers': 2.2.3 - cosmiconfig: 9.0.0(typescript@5.4.5) + '@puppeteer/browsers': 2.2.4 + cosmiconfig: 9.0.0(typescript@5.5.3) devtools-protocol: 0.0.1299070 - puppeteer-core: 22.12.0 + puppeteer-core: 22.13.1 transitivePeerDependencies: - bufferutil - supports-color - typescript - utf-8-validate + qs@6.11.0: + dependencies: + side-channel: 1.0.6 + queue-lit@1.5.2: {} queue-microtask@1.2.3: {} @@ -4822,7 +5274,14 @@ snapshots: dependencies: safe-buffer: 5.2.1 - react-is@18.3.1: {} + range-parser@1.2.1: {} + + raw-body@2.5.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 read-cache@1.0.0: dependencies: @@ -4889,45 +5348,45 @@ snapshots: dependencies: rollup-plugin-inject: 3.0.2 - rollup-plugin-tsc-alias@1.1.2(rollup@4.18.0): + rollup-plugin-tsc-alias@1.1.2(rollup@4.18.1): dependencies: - rollup: 4.18.0 + rollup: 4.18.1 tsc-alias: 1.8.10 - rollup-plugin-typescript2@0.36.0(rollup@4.18.0)(typescript@5.4.5): + rollup-plugin-typescript2@0.36.0(rollup@4.18.1)(typescript@5.5.3): dependencies: '@rollup/pluginutils': 4.2.1 find-cache-dir: 3.3.2 fs-extra: 10.1.0 - rollup: 4.18.0 + rollup: 4.18.1 semver: 7.6.2 tslib: 2.6.3 - typescript: 5.4.5 + typescript: 5.5.3 rollup-pluginutils@2.8.2: dependencies: estree-walker: 0.6.1 - rollup@4.18.0: + rollup@4.18.1: dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.18.0 - '@rollup/rollup-android-arm64': 4.18.0 - '@rollup/rollup-darwin-arm64': 4.18.0 - '@rollup/rollup-darwin-x64': 4.18.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 - '@rollup/rollup-linux-arm-musleabihf': 4.18.0 - '@rollup/rollup-linux-arm64-gnu': 4.18.0 - '@rollup/rollup-linux-arm64-musl': 4.18.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 - '@rollup/rollup-linux-riscv64-gnu': 4.18.0 - '@rollup/rollup-linux-s390x-gnu': 4.18.0 - '@rollup/rollup-linux-x64-gnu': 4.18.0 - '@rollup/rollup-linux-x64-musl': 4.18.0 - '@rollup/rollup-win32-arm64-msvc': 4.18.0 - '@rollup/rollup-win32-ia32-msvc': 4.18.0 - '@rollup/rollup-win32-x64-msvc': 4.18.0 + '@rollup/rollup-android-arm-eabi': 4.18.1 + '@rollup/rollup-android-arm64': 4.18.1 + '@rollup/rollup-darwin-arm64': 4.18.1 + '@rollup/rollup-darwin-x64': 4.18.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.18.1 + '@rollup/rollup-linux-arm-musleabihf': 4.18.1 + '@rollup/rollup-linux-arm64-gnu': 4.18.1 + '@rollup/rollup-linux-arm64-musl': 4.18.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.18.1 + '@rollup/rollup-linux-riscv64-gnu': 4.18.1 + '@rollup/rollup-linux-s390x-gnu': 4.18.1 + '@rollup/rollup-linux-x64-gnu': 4.18.1 + '@rollup/rollup-linux-x64-musl': 4.18.1 + '@rollup/rollup-win32-arm64-msvc': 4.18.1 + '@rollup/rollup-win32-ia32-msvc': 4.18.1 + '@rollup/rollup-win32-x64-msvc': 4.18.1 fsevents: 2.3.3 run-parallel@1.2.0: @@ -4946,6 +5405,8 @@ snapshots: safe-buffer@5.2.1: {} + safer-buffer@2.1.2: {} + sander@0.5.1: dependencies: es6-promise: 3.3.1 @@ -4955,20 +5416,56 @@ snapshots: semver@6.3.1: {} - semver@7.6.0: - dependencies: - lru-cache: 6.0.0 - semver@7.6.2: {} + semver@7.6.3: {} + + send@0.18.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + serialize-javascript@6.0.2: dependencies: randombytes: 2.1.0 + serve-static@1.15.0: + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + set-cookie-parser@2.6.0: {} + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + setimmediate@1.0.5: {} + setprototypeof@1.2.0: {} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -4977,6 +5474,13 @@ snapshots: shell-quote@1.8.1: {} + side-channel@1.0.6: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.2 + siginfo@2.0.0: {} signal-exit@3.0.7: {} @@ -5005,7 +5509,7 @@ snapshots: smob@1.5.0: {} - socks-proxy-agent@8.0.3: + socks-proxy-agent@8.0.4: dependencies: agent-base: 7.1.1 debug: 4.3.5 @@ -5020,7 +5524,7 @@ snapshots: sorcery@0.11.0: dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 buffer-crc32: 0.2.13 minimist: 1.2.8 sander: 0.5.1 @@ -5042,6 +5546,8 @@ snapshots: stackback@0.0.2: {} + statuses@2.0.1: {} + std-env@3.7.0: {} streamx@2.16.1: @@ -5055,7 +5561,7 @@ snapshots: dependencies: fast-fifo: 1.3.2 queue-tick: 1.0.1 - text-decoder: 1.1.0 + text-decoder: 1.1.1 optionalDependencies: bare-events: 2.4.2 optional: true @@ -5104,10 +5610,6 @@ snapshots: strip-json-comments@3.1.1: {} - strip-literal@2.1.0: - dependencies: - js-tokens: 9.0.0 - sucrase@3.35.0: dependencies: '@jridgewell/gen-mapping': 0.3.5 @@ -5132,17 +5634,15 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@3.8.1(postcss-load-config@4.0.2(postcss@8.4.38))(postcss@8.4.38)(svelte@4.2.18): + svelte-check@3.8.4(postcss-load-config@6.0.1(postcss@8.4.39))(postcss@8.4.39)(svelte@4.2.18): dependencies: '@jridgewell/trace-mapping': 0.3.25 chokidar: 3.6.0 - fast-glob: 3.3.2 - import-fresh: 3.3.0 picocolors: 1.0.1 sade: 1.8.1 svelte: 4.2.18 - svelte-preprocess: 5.1.4(postcss-load-config@4.0.2(postcss@8.4.38))(postcss@8.4.38)(svelte@4.2.18)(typescript@5.4.5) - typescript: 5.4.5 + svelte-preprocess: 5.1.4(postcss-load-config@6.0.1(postcss@8.4.39))(postcss@8.4.39)(svelte@4.2.18)(typescript@5.5.3) + typescript: 5.5.3 transitivePeerDependencies: - '@babel/core' - coffeescript @@ -5154,13 +5654,13 @@ snapshots: - stylus - sugarss - svelte-eslint-parser@0.39.1(svelte@4.2.18): + svelte-eslint-parser@0.40.0(svelte@4.2.18): dependencies: eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 espree: 9.6.1 - postcss: 8.4.38 - postcss-scss: 4.0.9(postcss@8.4.38) + postcss: 8.4.39 + postcss-scss: 4.0.9(postcss@8.4.39) optionalDependencies: svelte: 4.2.18 @@ -5173,7 +5673,7 @@ snapshots: dependencies: svelte: 4.2.18 - svelte-preprocess@5.1.4(postcss-load-config@4.0.2(postcss@8.4.38))(postcss@8.4.38)(svelte@4.2.18)(typescript@5.4.5): + svelte-preprocess@5.1.4(postcss-load-config@6.0.1(postcss@8.4.39))(postcss@8.4.39)(svelte@4.2.18)(typescript@5.5.3): dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 @@ -5182,9 +5682,9 @@ snapshots: strip-indent: 3.0.0 svelte: 4.2.18 optionalDependencies: - postcss: 8.4.38 - postcss-load-config: 4.0.2(postcss@8.4.38) - typescript: 5.4.5 + postcss: 8.4.39 + postcss-load-config: 6.0.1(postcss@8.4.39) + typescript: 5.5.3 svelte@4.2.18: dependencies: @@ -5203,12 +5703,12 @@ snapshots: magic-string: 0.30.10 periscopic: 3.1.0 - synckit@0.8.8: + synckit@0.9.1: dependencies: '@pkgr/core': 0.1.1 tslib: 2.6.3 - tailwindcss@3.4.4: + tailwindcss@3.4.6: dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -5224,18 +5724,18 @@ snapshots: normalize-path: 3.0.0 object-hash: 3.0.0 picocolors: 1.0.1 - postcss: 8.4.38 - postcss-import: 15.1.0(postcss@8.4.38) - postcss-js: 4.0.1(postcss@8.4.38) - postcss-load-config: 4.0.2(postcss@8.4.38) - postcss-nested: 6.0.1(postcss@8.4.38) + postcss: 8.4.39 + postcss-import: 15.1.0(postcss@8.4.39) + postcss-js: 4.0.1(postcss@8.4.39) + postcss-load-config: 4.0.2(postcss@8.4.39) + postcss-nested: 6.0.1(postcss@8.4.39) postcss-selector-parser: 6.0.16 resolve: 1.22.8 sucrase: 3.35.0 transitivePeerDependencies: - ts-node - tar-fs@3.0.5: + tar-fs@3.0.6: dependencies: pump: 3.0.0 tar-stream: 3.1.7 @@ -5256,7 +5756,15 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 - text-decoder@1.1.0: + terser@5.31.3: + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.12.1 + commander: 2.20.3 + source-map-support: 0.5.21 + optional: true + + text-decoder@1.1.1: dependencies: b4a: 1.6.6 optional: true @@ -5280,21 +5788,25 @@ snapshots: tinybench@2.8.0: {} - tinypool@0.8.4: {} + tinypool@1.0.0: {} + + tinyrainbow@1.2.0: {} - tinyspy@2.2.1: {} + tinyspy@3.0.0: {} to-regex-range@5.0.1: dependencies: is-number: 7.0.0 + toidentifier@1.0.1: {} + totalist@3.0.1: {} tree-kill@1.2.2: {} - ts-api-utils@1.3.0(typescript@5.4.5): + ts-api-utils@1.3.0(typescript@5.5.3): dependencies: - typescript: 5.4.5 + typescript: 5.5.3 ts-interface-checker@0.1.13: {} @@ -5309,26 +5821,29 @@ snapshots: tslib@2.6.3: {} + tweetnacl@1.0.3: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 - type-detect@4.0.8: {} + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 - typescript-eslint@7.13.1(eslint@9.5.0)(typescript@5.4.5): + typescript-eslint@7.16.1(eslint@9.7.0)(typescript@5.5.3): dependencies: - '@typescript-eslint/eslint-plugin': 7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/parser': 7.13.1(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.13.1(eslint@9.5.0)(typescript@5.4.5) - eslint: 9.5.0 + '@typescript-eslint/eslint-plugin': 7.16.1(@typescript-eslint/parser@7.16.1(eslint@9.7.0)(typescript@5.5.3))(eslint@9.7.0)(typescript@5.5.3) + '@typescript-eslint/parser': 7.16.1(eslint@9.7.0)(typescript@5.5.3) + '@typescript-eslint/utils': 7.16.1(eslint@9.7.0)(typescript@5.5.3) + eslint: 9.7.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - typescript@5.4.5: {} - - ufo@1.5.3: {} + typescript@5.5.3: {} uid@2.0.2: dependencies: @@ -5339,11 +5854,12 @@ snapshots: buffer: 5.7.1 through: 2.3.8 - undici-types@5.26.5: - optional: true + undici-types@5.26.5: {} universalify@2.0.1: {} + unpipe@1.0.0: {} + update-browserslist-db@1.0.16(browserslist@4.23.0): dependencies: browserslist: 4.23.0 @@ -5358,13 +5874,17 @@ snapshots: util-deprecate@1.0.2: {} - vite-node@1.6.0(@types/node@20.14.8)(terser@5.31.0): + utils-merge@1.0.1: {} + + vary@1.1.2: {} + + vite-node@2.0.3(@types/node@20.14.11)(terser@5.31.3): dependencies: cac: 6.7.14 debug: 4.3.5 pathe: 1.1.2 - picocolors: 1.0.1 - vite: 5.3.1(@types/node@20.14.8)(terser@5.31.0) + tinyrainbow: 1.2.0 + vite: 5.3.4(@types/node@20.14.11)(terser@5.31.3) transitivePeerDependencies: - '@types/node' - less @@ -5375,45 +5895,44 @@ snapshots: - supports-color - terser - vite@5.3.1(@types/node@20.14.8)(terser@5.31.0): + vite@5.3.4(@types/node@20.14.11)(terser@5.31.3): dependencies: esbuild: 0.21.5 - postcss: 8.4.38 - rollup: 4.18.0 + postcss: 8.4.39 + rollup: 4.18.1 optionalDependencies: - '@types/node': 20.14.8 + '@types/node': 20.14.11 fsevents: 2.3.3 - terser: 5.31.0 + terser: 5.31.3 - vitefu@0.2.5(vite@5.3.1(@types/node@20.14.8)(terser@5.31.0)): + vitefu@0.2.5(vite@5.3.4(@types/node@20.14.11)(terser@5.31.3)): optionalDependencies: - vite: 5.3.1(@types/node@20.14.8)(terser@5.31.0) + vite: 5.3.4(@types/node@20.14.11)(terser@5.31.3) - vitest@1.6.0(@types/node@20.14.8)(@vitest/ui@1.6.0)(terser@5.31.0): + vitest@2.0.3(@types/node@20.14.11)(@vitest/ui@2.0.3)(terser@5.31.3): dependencies: - '@vitest/expect': 1.6.0 - '@vitest/runner': 1.6.0 - '@vitest/snapshot': 1.6.0 - '@vitest/spy': 1.6.0 - '@vitest/utils': 1.6.0 - acorn-walk: 8.3.3 - chai: 4.4.1 + '@ampproject/remapping': 2.3.0 + '@vitest/expect': 2.0.3 + '@vitest/pretty-format': 2.0.3 + '@vitest/runner': 2.0.3 + '@vitest/snapshot': 2.0.3 + '@vitest/spy': 2.0.3 + '@vitest/utils': 2.0.3 + chai: 5.1.1 debug: 4.3.5 execa: 8.0.1 - local-pkg: 0.5.0 magic-string: 0.30.10 pathe: 1.1.2 - picocolors: 1.0.1 std-env: 3.7.0 - strip-literal: 2.1.0 tinybench: 2.8.0 - tinypool: 0.8.4 - vite: 5.3.1(@types/node@20.14.8)(terser@5.31.0) - vite-node: 1.6.0(@types/node@20.14.8)(terser@5.31.0) - why-is-node-running: 2.2.2 + tinypool: 1.0.0 + tinyrainbow: 1.2.0 + vite: 5.3.4(@types/node@20.14.11)(terser@5.31.3) + vite-node: 2.0.3(@types/node@20.14.11)(terser@5.31.3) + why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 20.14.8 - '@vitest/ui': 1.6.0(vitest@1.6.0) + '@types/node': 20.14.11 + '@vitest/ui': 2.0.3(vitest@2.0.3) transitivePeerDependencies: - less - lightningcss @@ -5427,7 +5946,7 @@ snapshots: dependencies: isexe: 2.0.0 - why-is-node-running@2.2.2: + why-is-node-running@2.3.0: dependencies: siginfo: 2.0.0 stackback: 0.0.2 @@ -5454,12 +5973,10 @@ snapshots: wrappy@1.0.2: {} - ws@8.17.1: {} + ws@8.18.0: {} y18n@5.0.8: {} - yallist@4.0.0: {} - yaml@1.10.2: {} yaml@2.4.2: {} @@ -5483,8 +6000,6 @@ snapshots: yocto-queue@0.1.0: {} - yocto-queue@1.0.0: {} - zip-stream@6.0.1: dependencies: archiver-utils: 5.0.2 diff --git a/tests/clientInteraction.ts b/tests/clientInteraction.ts new file mode 100644 index 0000000..5a7c88a --- /dev/null +++ b/tests/clientInteraction.ts @@ -0,0 +1,100 @@ +import { Browser } from 'puppeteer'; +import { expect } from 'vitest'; + +import { + createSignUpExtensionPage, + extractUint8ArrayFromResult, + findButtonExtensionByText, + findTextBySelector, + validateSignature +} from './helpers'; + +export default async function clientInteractionTest(browser: Browser) { + const appPage = await browser.newPage(); + await appPage.goto('http://localhost:3000/tests/test.html'); + + const findTextOnAppPage = findTextBySelector(appPage); + + const signUpButton = await findTextOnAppPage('Sign Up'); + expect(signUpButton).toBeTruthy(); + + const { apiCallSpy, signUpExtensionPage } = await createSignUpExtensionPage(browser, () => + signUpButton.click() + ); + + expect(signUpExtensionPage).toBeTruthy(); + + const findTextOnSignUpExtensionPage = findTextBySelector(signUpExtensionPage); + const findButtonOnSignUpExtensionPage = findButtonExtensionByText(signUpExtensionPage); + + const saveSeedText = await findTextOnSignUpExtensionPage( + 'Please enter your password to login into Holo Key Manager' + ); + + expect(saveSeedText).toBeTruthy(); + + await signUpExtensionPage.type('input[id="enter-password"]', 'password'); + + const loginButton = await findButtonOnSignUpExtensionPage('Login'); + + await loginButton.click(); + + const connectButton = await findButtonOnSignUpExtensionPage('Connect'); + + expect(connectButton).toBeTruthy(); + + await Promise.all([signUpExtensionPage.waitForNavigation(), connectButton.click()]); + + const requestDetailsText = await findTextOnSignUpExtensionPage( + 'This app is requesting the following details' + ); + + expect(requestDetailsText).toBeTruthy(); + + await signUpExtensionPage.type('input[id*="email"]', 'test@test.com'); + await signUpExtensionPage.type('input[id*="name-this-key"]', 'Test1'); + + const createButton = await findButtonOnSignUpExtensionPage('Create'); + + expect(createButton).toBeTruthy(); + + await Promise.all([ + createButton.click(), + new Promise((resolve) => signUpExtensionPage.once('close', resolve)) + ]); + + expect(apiCallSpy).toHaveBeenCalledWith( + expect.objectContaining({ + appIndex: 1, + keyName: 'Test1' + }) + ); + + const pubKey = await extractUint8ArrayFromResult(appPage, 'signUpBtnResult', 'pubKey'); + expect(pubKey).toBeInstanceOf(Uint8Array); + expect(pubKey.length).toBe(32); + + const messageInput = '[1,2,3]'; + + await appPage.type('input[id="messageInput"]', messageInput); + + const signMessageBtn = await findTextOnAppPage('Sign Message'); + expect(signMessageBtn).toBeTruthy(); + + await signMessageBtn.click(); + + await new Promise((resolve) => setTimeout(resolve, 2000)); + + const signedMessage = await extractUint8ArrayFromResult( + appPage, + 'signMessageBtnResult', + 'signedMessage' + ); + + expect(signedMessage).toBeInstanceOf(Uint8Array); + expect(signedMessage.length).toBe(64); + + const result = validateSignature(pubKey, signedMessage, new Uint8Array(JSON.parse(messageInput))); + + expect(result).toBe(true); +} diff --git a/tests/helpers.ts b/tests/helpers.ts index a059c93..d5a3ba6 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -1,5 +1,10 @@ +import express from 'express'; import { access, constants } from 'fs'; +import type { Server } from 'http'; +import { resolve } from 'path'; import { Browser, launch, Locator, Page } from 'puppeteer'; +import nacl from 'tweetnacl'; +import { vi } from 'vitest'; export const launchBrowserWithExtension = async (extensionPath: string): Promise => { return launch({ @@ -14,14 +19,6 @@ export const openExtensionPage = async (browser: Browser, extensionId: string): return page; }; -const waitForNewPage = (browser: Browser): Promise => - new Promise((resolve, reject) => - browser.once('targetcreated', async (target) => { - const page = await target.page(); - page ? resolve(page) : reject(new Error('Failed to create new page')); - }) - ); - export const clickButtonAndWaitForNewPage = async ( browser: Browser, button: Locator, @@ -60,6 +57,91 @@ const findElementByText = (context: Page, selector: string) => async (text: stri return locator; }; -export const findButtonByText = (context: Page) => +export const findButtonExtensionByText = (context: Page) => findElementByText(context, 'button:not(:disabled) > span'); export const findTextBySelector = (context: Page) => findElementByText(context, ''); + +export const startServer = (port: number = 3000): Server => { + const app = express(); + app.use(express.static(resolve('./holo-key-manager-js-client'))); + return app.listen(port); +}; + +export const startOtherServer = (): Server => { + const app = express(); + app.use(express.static(resolve('./holo-key-manager-js-client'))); + return app.listen(4000); +}; + +export const waitForNewPage = (browser: Browser): Promise => + new Promise((resolve, reject) => + browser.once('targetcreated', async (target) => { + const page = await target.page(); + page ? resolve(page) : reject(new Error('Failed to create new page')); + }) + ); + +export const apiEndpoints = { + 'data-object': { status: 200, contentType: 'application/json', body: JSON.stringify([]) }, + 'register-key': { status: 200, contentType: 'application/json', body: JSON.stringify({}) } +} as const; + +export const createSignUpExtensionPage = async (browser: Browser, buttonClick: () => void) => { + const apiCallSpy = vi.fn(); + + const newPagePromise = waitForNewPage(browser); + + buttonClick(); + + const signUpExtensionPage = await newPagePromise; + + signUpExtensionPage.setRequestInterception(true); + + signUpExtensionPage.on('request', (request) => { + const endpoint = Object.keys(apiEndpoints).find((key) => + request.url().includes(`key-manager-store.holo.host/api/v1/${key}`) + ); + + if (endpoint && endpoint in apiEndpoints) { + if (endpoint === 'register-key') { + apiCallSpy(JSON.parse(request.postData() ?? '')); + } + request.respond(apiEndpoints[endpoint as keyof typeof apiEndpoints]); + } else { + request.continue(); + } + }); + + return { apiCallSpy, signUpExtensionPage }; +}; + +export const extractUint8ArrayFromResult = async ( + page: Page, + id: string, + key: string +): Promise => { + const resultLocator = page.locator(`#${id}`); + await resultLocator.wait(); + + const resultText = await resultLocator.map((element) => element.textContent).wait(); + + const match = resultText?.match(/successful: (.*)/); + + if (!match) { + throw new Error(`Expected ${id} result not found in page content`); + } + + const result = JSON.parse(match[1]); + const array = Object.values(result[key]); + return new Uint8Array(array as number[]); +}; + +export const validateSignature = ( + publicKey: Uint8Array, + signedMessage: Uint8Array, + originalMessage: Uint8Array +) => { + const isValid = nacl.sign.detached.verify(originalMessage, signedMessage, publicKey); + + return isValid; +}; diff --git a/tests/index.test.ts b/tests/index.test.ts index b197fbf..d03ca4b 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,18 +1,15 @@ import dotenv from 'dotenv'; -import { readFile, rm } from 'fs/promises'; -import JSZip from 'jszip'; -import { join, resolve } from 'path'; -import type { Browser, Page } from 'puppeteer'; -import { afterAll, beforeAll, describe, expect, it } from 'vitest'; - -import { - clickButtonAndWaitForNewPage, - fileExists, - findButtonByText, - findTextBySelector, - launchBrowserWithExtension, - openExtensionPage -} from './helpers'; +import { rm } from 'fs/promises'; +import { Server } from 'http'; +import { resolve } from 'path'; +import type { Browser } from 'puppeteer'; +import { afterAll, beforeAll, describe, it } from 'vitest'; + +import clientInteractionTest from './clientInteraction'; +import { launchBrowserWithExtension, startServer } from './helpers'; +import needsSetupTest from './needsSetup'; +import preventSignatureFromOtherOrigin from './preventSignatureFromOtherOrigin'; +import setupFlowTest from './setupFlow'; dotenv.config(); @@ -21,7 +18,7 @@ const EXTENSION_ID = process.env.CHROME_ID; const downloadPath = resolve('./downloads'); let browser: Browser; -let page: Page; +let server: Server; beforeAll(async () => { if (!EXTENSION_ID) { @@ -29,139 +26,29 @@ beforeAll(async () => { } const extensionPath = resolve('holo-key-manager-extension', 'build'); browser = await launchBrowserWithExtension(extensionPath); - page = await openExtensionPage(browser, EXTENSION_ID); + server = startServer(); }); afterAll(async () => { await rm(downloadPath, { recursive: true, force: true }); await browser?.close(); + server.close(); }); -describe('Extension E2E Tests', () => { - it('Setup flow is working properly', async () => { - console.log('Finding Setup button'); - const setupButton = await findButtonByText(page)('Setup'); - - console.log('Finding Setup Required text'); - const setupPageContent = await findTextBySelector(page)('Setup Required'); - - expect(setupPageContent).toBeTruthy(); - - console.log('Clicking Setup button and waiting for new page'); - const setupPage = await clickButtonAndWaitForNewPage(browser, setupButton, downloadPath); - - const findButtonOnSetupPage = findButtonByText(setupPage); - const findTextOnSetupPage = findTextBySelector(setupPage); - - console.log('Finding Holo Key Manager text'); - const setupPageText = await findTextOnSetupPage( - 'Holo Key Manager is a safe place to set up and manage keys for Holochain apps' - ); - - expect(setupPageText).toBeTruthy(); - - console.log('Finding First time set up button'); - const firstTimeSetupButton = await findButtonOnSetupPage('First time set up'); - - console.log('Clicking First time set up button and waiting for navigation'); - await Promise.all([setupPage.waitForNavigation(), firstTimeSetupButton.click()]); - - console.log('Finding Set Key Manager Password text'); - const setKeyManagerPasswordText = await findTextOnSetupPage('Set Key Manager Password'); - - expect(setKeyManagerPasswordText).toBeTruthy(); - - console.log('Typing enter-password'); - await setupPage.type('input[id*="enter-password"]', 'password'); - - console.log('Typing confirm-password'); - await setupPage.type('input[id="confirm-password"]', 'password'); - - console.log('Finding Set password button'); - const setPasswordButton = await findButtonOnSetupPage('Set password'); - - console.log('Clicking Set password button and waiting for navigation'); - await Promise.all([setupPage.waitForNavigation(), setPasswordButton.click()]); - - console.log('Finding I understand button'); - const iUnderstandButton = await findButtonOnSetupPage('I understand'); - - expect(iUnderstandButton).toBeTruthy(); - - console.log('Clicking Set password button and waiting for navigation'); - await Promise.all([setupPage.waitForNavigation(), iUnderstandButton.click()]); - - console.log('Finding Enter Passphrase text'); - const enterPassphraseText = await findTextOnSetupPage('Enter Passphrase'); - - expect(enterPassphraseText).toBeTruthy(); - - console.log('Typing passphrase'); - await setupPage.type('textarea[placeholder="Enter Passphrase"]', 'passphrase passphrase'); - - console.log('Finding Set passphrase button'); - const setPassphraseButton = await findButtonOnSetupPage('Set passphrase'); - - console.log('Clicking Set passphrase button'); - await setPassphraseButton.click(); - - console.log('Finding Confirm Passphrase text'); - const confirmPassphraseText = await findTextOnSetupPage('Confirm Passphrase'); - - expect(confirmPassphraseText).toBeTruthy(); - - console.log('Typing confirm passphrase'); - await setupPage.type('textarea[placeholder="Confirm Passphrase"]', 'passphrase passphrase'); - - console.log('Finding Next button'); - const confirmPassphraseButton = await findButtonOnSetupPage('Next'); - - console.log('Clicking Next button and waiting for navigation'); - await Promise.all([setupPage.waitForNavigation(), confirmPassphraseButton.click()]); - - console.log('Finding Generate seed and key files text'); - const generateSeedText = await findTextOnSetupPage('Generate seed and key files'); - - expect(generateSeedText).toBeTruthy(); - - console.log('Finding Generate button'); - const generateSeedButton = await findButtonOnSetupPage('Generate'); - - console.log('Clicking Generate button and waiting for navigation'); - await Promise.all([setupPage.waitForNavigation(), generateSeedButton.click()]); - - console.log('Finding Save seed and key files text'); - const saveSeedText = await findTextOnSetupPage('Save seed and key files'); - - expect(saveSeedText).toBeTruthy(); - - console.log('Finding Save button'); - const exportButton = await findButtonOnSetupPage('Save'); - - console.log('Clicking Export button'); - exportButton.click(); - - console.log('Checking if keys file exists'); - const keysFilePath = join(downloadPath, 'keys.zip'); - const keysFileExists = await fileExists(keysFilePath); - - expect(keysFileExists).toBe(true); - - console.log('Reading keys file'); - const zipContent = await readFile(keysFilePath); - const zip = await JSZip.loadAsync(zipContent); - - console.log('Checking keys file content'); - const expectedFiles = ['device.txt', 'master.txt', 'revocation.txt']; - const actualFiles = Object.keys(zip.files); - - expectedFiles.forEach((file) => { - expect(actualFiles).toContain(file); - }); - - console.log('Finding Setup Complete text'); - const setupCompleteText = await findTextOnSetupPage('Setup Complete'); - - expect(setupCompleteText).toBeTruthy(); - }, 10000); +describe('End-to-End Tests for Extension and Client', () => { + it('should allow the client to interact with the extension after setup', async () => { + await needsSetupTest(browser); + }); + it('verify setup flow works as expected', async () => { + if (!EXTENSION_ID) { + throw new Error('EXTENSION_ID is not set'); + } + await setupFlowTest(browser, EXTENSION_ID); + }); + it('should allow the client to interact with the extension after setup', async () => { + await clientInteractionTest(browser); + }); + it('should prevent the malicious page from signing messages', async () => { + await preventSignatureFromOtherOrigin(browser); + }); }); diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts new file mode 100644 index 0000000..b8d41d1 --- /dev/null +++ b/tests/needsSetup.ts @@ -0,0 +1,19 @@ +import { Browser } from 'puppeteer'; +import { expect } from 'vitest'; + +import { findTextBySelector } from './helpers'; + +export default async function needsSetupTest(browser: Browser) { + const page = await browser.newPage(); + await page.goto('http://localhost:3000/tests/test.html'); + + const findTextOnPage = findTextBySelector(page); + + const signUpButton = await findTextOnPage('Sign Up'); + expect(signUpButton).toBeTruthy(); + + await signUpButton.click(); + + const needsSetupText = await findTextOnPage('NeedsSetup'); + expect(needsSetupText).toBeTruthy(); +} diff --git a/tests/preventSignatureFromOtherOrigin.ts b/tests/preventSignatureFromOtherOrigin.ts new file mode 100644 index 0000000..5ad7009 --- /dev/null +++ b/tests/preventSignatureFromOtherOrigin.ts @@ -0,0 +1,59 @@ +import { Browser } from 'puppeteer'; +import { expect } from 'vitest'; + +import { startServer } from './helpers'; + +export default async function preventSignatureFromOtherOrigin(browser: Browser) { + const server = startServer(4000); + + const maliciousPage = await browser.newPage(); + await maliciousPage.goto('http://localhost:4000'); + + try { + const result = await maliciousPage.evaluate(async () => { + const message = new Uint8Array([1, 2, 3]); + const messageId = Date.now().toString(); + + return new Promise((resolve, reject) => { + const responseHandler = (event: MessageEvent) => { + if (event.data.id === messageId && event.data.sender !== 'webapp') { + window.removeEventListener('message', responseHandler); + resolve(event.data); + } + }; + + window.addEventListener('message', responseHandler); + + window.postMessage( + { + action: 'SignMessage', + id: messageId, + payload: { + message: message.toString(), + happId: 'your-happId' + }, + sender: 'webapp', + appId: 'holo-key-manager' + }, + '*' + ); + setTimeout(() => { + window.removeEventListener('message', responseHandler); + reject(new Error('Timeout: No response received')); + }, 5000); + }); + }); + + const isValidResult = (result: unknown): result is { action: string } => + typeof result === 'object' && result !== null && 'action' in result; + + if (isValidResult(result)) { + expect(result.action).toBe('AppNotAuthenticated'); + } else { + throw new Error('Unexpected result structure'); + } + } finally { + await maliciousPage.close(); + server.close(); + } +} diff --git a/tests/setupFlow.ts b/tests/setupFlow.ts new file mode 100644 index 0000000..46878c6 --- /dev/null +++ b/tests/setupFlow.ts @@ -0,0 +1,116 @@ +import { readFile } from 'fs/promises'; +import JSZip from 'jszip'; +import { join, resolve } from 'path'; +import { Browser } from 'puppeteer'; +import { expect } from 'vitest'; + +import { + clickButtonAndWaitForNewPage, + fileExists, + findButtonExtensionByText, + findTextBySelector, + openExtensionPage +} from './helpers'; + +const downloadPath = resolve('./downloads'); + +export default async function setupFlowTest(browser: Browser, EXTENSION_ID: string) { + if (!EXTENSION_ID) { + throw new Error('EXTENSION_ID is not set'); + } + const page = await openExtensionPage(browser, EXTENSION_ID); + + const setupButton = await findButtonExtensionByText(page)('Setup'); + + const setupPageContent = await findTextBySelector(page)('Setup Required'); + + expect(setupPageContent).toBeTruthy(); + + const setupPage = await clickButtonAndWaitForNewPage(browser, setupButton, downloadPath); + + const findButtonOnSetupPage = findButtonExtensionByText(setupPage); + const findTextOnSetupPage = findTextBySelector(setupPage); + + const setupPageText = await findTextOnSetupPage( + 'Holo Key Manager is a safe place to set up and manage keys for Holochain apps' + ); + + expect(setupPageText).toBeTruthy(); + + const firstTimeSetupButton = await findButtonOnSetupPage('First time set up'); + + await Promise.all([setupPage.waitForNavigation(), firstTimeSetupButton.click()]); + + const setKeyManagerPasswordText = await findTextOnSetupPage('Set Key Manager Password'); + + expect(setKeyManagerPasswordText).toBeTruthy(); + + await setupPage.type('input[id*="enter-password"]', 'password'); + + await setupPage.type('input[id="confirm-password"]', 'password'); + + const setPasswordButton = await findButtonOnSetupPage('Set password'); + + await Promise.all([setupPage.waitForNavigation(), setPasswordButton.click()]); + + const iUnderstandButton = await findButtonOnSetupPage('I understand'); + + expect(iUnderstandButton).toBeTruthy(); + + await Promise.all([setupPage.waitForNavigation(), iUnderstandButton.click()]); + + const enterPassphraseText = await findTextOnSetupPage('Enter Passphrase'); + + expect(enterPassphraseText).toBeTruthy(); + + await setupPage.type('textarea[placeholder="Enter Passphrase"]', 'passphrase passphrase'); + + const setPassphraseButton = await findButtonOnSetupPage('Set passphrase'); + + await setPassphraseButton.click(); + + const confirmPassphraseText = await findTextOnSetupPage('Confirm Passphrase'); + + expect(confirmPassphraseText).toBeTruthy(); + + await setupPage.type('textarea[placeholder="Confirm Passphrase"]', 'passphrase passphrase'); + + const confirmPassphraseButton = await findButtonOnSetupPage('Next'); + + await Promise.all([setupPage.waitForNavigation(), confirmPassphraseButton.click()]); + + const generateSeedText = await findTextOnSetupPage('Generate seed and key files'); + + expect(generateSeedText).toBeTruthy(); + + const generateSeedButton = await findButtonOnSetupPage('Generate'); + + await Promise.all([setupPage.waitForNavigation(), generateSeedButton.click()]); + + const saveSeedText = await findTextOnSetupPage('Save seed and key files'); + + expect(saveSeedText).toBeTruthy(); + + const exportButton = await findButtonOnSetupPage('Save'); + + exportButton.click(); + + const keysFilePath = join(downloadPath, 'keys.zip'); + const keysFileExists = await fileExists(keysFilePath); + + expect(keysFileExists).toBe(true); + + const zipContent = await readFile(keysFilePath); + const zip = await JSZip.loadAsync(zipContent); + + const expectedFiles = ['device.txt', 'master.txt', 'revocation.txt']; + const actualFiles = Object.keys(zip.files); + + expectedFiles.forEach((file) => { + expect(actualFiles).toContain(file); + }); + + const setupCompleteText = await findTextOnSetupPage('Setup Complete'); + + expect(setupCompleteText).toBeTruthy(); +} diff --git a/tests/tsconfig.json b/tests/tsconfig.json new file mode 100644 index 0000000..b525b91 --- /dev/null +++ b/tests/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../tsconfig.base.json", + "include": ["**/*.ts"] +} diff --git a/vitest.config.ts b/vitest.config.ts index 6d4f445..d68d91f 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,3 +1,4 @@ +import path from 'path'; import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -5,5 +6,10 @@ export default defineConfig({ globals: true, environment: 'node', include: ['tests/**/*.test.ts'] + }, + resolve: { + alias: { + $types: path.resolve('./holo-key-manager-extension/src/lib/types') + } } }); From f752da2928104aa8998a56673799f74588428a71 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Wed, 17 Jul 2024 18:19:53 +0200 Subject: [PATCH 02/49] Fix timeout --- tests/index.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/index.test.ts b/tests/index.test.ts index d03ca4b..4091d8f 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -44,10 +44,10 @@ describe('End-to-End Tests for Extension and Client', () => { throw new Error('EXTENSION_ID is not set'); } await setupFlowTest(browser, EXTENSION_ID); - }); + }, 10000); it('should allow the client to interact with the extension after setup', async () => { await clientInteractionTest(browser); - }); + }, 10000); it('should prevent the malicious page from signing messages', async () => { await preventSignatureFromOtherOrigin(browser); }); From a8175f3a67177ec9281cac606eb936edc49287e4 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Wed, 17 Jul 2024 18:25:12 +0200 Subject: [PATCH 03/49] Fix sequential --- tests/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/index.test.ts b/tests/index.test.ts index 4091d8f..da43e7d 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -35,7 +35,7 @@ afterAll(async () => { server.close(); }); -describe('End-to-End Tests for Extension and Client', () => { +describe.sequential('End-to-End Tests for Extension and Client', () => { it('should allow the client to interact with the extension after setup', async () => { await needsSetupTest(browser); }); From 507e3f79b56ed266b87f4d5518ab76654194e982 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Wed, 17 Jul 2024 18:28:12 +0200 Subject: [PATCH 04/49] console.log to test --- tests/setupFlow.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/setupFlow.ts b/tests/setupFlow.ts index 46878c6..61ae4ab 100644 --- a/tests/setupFlow.ts +++ b/tests/setupFlow.ts @@ -18,88 +18,109 @@ export default async function setupFlowTest(browser: Browser, EXTENSION_ID: stri if (!EXTENSION_ID) { throw new Error('EXTENSION_ID is not set'); } + console.log('Starting setup flow test'); const page = await openExtensionPage(browser, EXTENSION_ID); + console.log('Finding setup button'); const setupButton = await findButtonExtensionByText(page)('Setup'); + console.log('Checking for setup page content'); const setupPageContent = await findTextBySelector(page)('Setup Required'); expect(setupPageContent).toBeTruthy(); + console.log('Clicking setup button and waiting for new page'); const setupPage = await clickButtonAndWaitForNewPage(browser, setupButton, downloadPath); const findButtonOnSetupPage = findButtonExtensionByText(setupPage); const findTextOnSetupPage = findTextBySelector(setupPage); + console.log('Verifying setup page text'); const setupPageText = await findTextOnSetupPage( 'Holo Key Manager is a safe place to set up and manage keys for Holochain apps' ); expect(setupPageText).toBeTruthy(); + console.log('Clicking first time setup button'); const firstTimeSetupButton = await findButtonOnSetupPage('First time set up'); await Promise.all([setupPage.waitForNavigation(), firstTimeSetupButton.click()]); + console.log('Verifying password setup page'); const setKeyManagerPasswordText = await findTextOnSetupPage('Set Key Manager Password'); expect(setKeyManagerPasswordText).toBeTruthy(); + console.log('Entering password'); await setupPage.type('input[id*="enter-password"]', 'password'); await setupPage.type('input[id="confirm-password"]', 'password'); + console.log('Setting password'); const setPasswordButton = await findButtonOnSetupPage('Set password'); await Promise.all([setupPage.waitForNavigation(), setPasswordButton.click()]); + console.log('Clicking "I understand" button'); const iUnderstandButton = await findButtonOnSetupPage('I understand'); expect(iUnderstandButton).toBeTruthy(); await Promise.all([setupPage.waitForNavigation(), iUnderstandButton.click()]); + console.log('Verifying passphrase entry page'); const enterPassphraseText = await findTextOnSetupPage('Enter Passphrase'); expect(enterPassphraseText).toBeTruthy(); + console.log('Entering passphrase'); await setupPage.type('textarea[placeholder="Enter Passphrase"]', 'passphrase passphrase'); + console.log('Setting passphrase'); const setPassphraseButton = await findButtonOnSetupPage('Set passphrase'); await setPassphraseButton.click(); + console.log('Verifying passphrase confirmation page'); const confirmPassphraseText = await findTextOnSetupPage('Confirm Passphrase'); expect(confirmPassphraseText).toBeTruthy(); + console.log('Confirming passphrase'); await setupPage.type('textarea[placeholder="Confirm Passphrase"]', 'passphrase passphrase'); const confirmPassphraseButton = await findButtonOnSetupPage('Next'); await Promise.all([setupPage.waitForNavigation(), confirmPassphraseButton.click()]); + console.log('Verifying seed generation page'); const generateSeedText = await findTextOnSetupPage('Generate seed and key files'); expect(generateSeedText).toBeTruthy(); + console.log('Generating seed'); const generateSeedButton = await findButtonOnSetupPage('Generate'); await Promise.all([setupPage.waitForNavigation(), generateSeedButton.click()]); + console.log('Verifying seed saving page'); const saveSeedText = await findTextOnSetupPage('Save seed and key files'); expect(saveSeedText).toBeTruthy(); + console.log('Saving seed and key files'); const exportButton = await findButtonOnSetupPage('Save'); exportButton.click(); + console.log('Verifying downloaded keys file'); const keysFilePath = join(downloadPath, 'keys.zip'); const keysFileExists = await fileExists(keysFilePath); expect(keysFileExists).toBe(true); + console.log('Checking contents of keys file'); const zipContent = await readFile(keysFilePath); const zip = await JSZip.loadAsync(zipContent); @@ -110,7 +131,9 @@ export default async function setupFlowTest(browser: Browser, EXTENSION_ID: stri expect(actualFiles).toContain(file); }); + console.log('Verifying setup completion'); const setupCompleteText = await findTextOnSetupPage('Setup Complete'); expect(setupCompleteText).toBeTruthy(); + console.log('Setup flow test completed successfully'); } From eb754b53d669969d1d14039aecedc68d0bea9069 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Wed, 17 Jul 2024 18:31:09 +0200 Subject: [PATCH 05/49] Add return --- .github/workflows/extension-PR.yaml | 2 +- tests/clientInteraction.ts | 2 +- tests/needsSetup.ts | 2 +- tests/preventSignatureFromOtherOrigin.ts | 2 +- tests/setupFlow.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/extension-PR.yaml b/.github/workflows/extension-PR.yaml index 6db9e03..517b9dc 100644 --- a/.github/workflows/extension-PR.yaml +++ b/.github/workflows/extension-PR.yaml @@ -34,7 +34,7 @@ jobs: working-directory: holo-key-manager-extension - name: Build and pack client - run: pnpm buildPack + run: pnpm build working-directory: holo-key-manager-js-client - name: Run e2e tests diff --git a/tests/clientInteraction.ts b/tests/clientInteraction.ts index 5a7c88a..3f8445a 100644 --- a/tests/clientInteraction.ts +++ b/tests/clientInteraction.ts @@ -96,5 +96,5 @@ export default async function clientInteractionTest(browser: Browser) { const result = validateSignature(pubKey, signedMessage, new Uint8Array(JSON.parse(messageInput))); - expect(result).toBe(true); + return expect(result).toBe(true); } diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index b8d41d1..a32bc8b 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -15,5 +15,5 @@ export default async function needsSetupTest(browser: Browser) { await signUpButton.click(); const needsSetupText = await findTextOnPage('NeedsSetup'); - expect(needsSetupText).toBeTruthy(); + return expect(needsSetupText).toBeTruthy(); } diff --git a/tests/preventSignatureFromOtherOrigin.ts b/tests/preventSignatureFromOtherOrigin.ts index 5ad7009..35874cb 100644 --- a/tests/preventSignatureFromOtherOrigin.ts +++ b/tests/preventSignatureFromOtherOrigin.ts @@ -48,7 +48,7 @@ export default async function preventSignatureFromOtherOrigin(browser: Browser) typeof result === 'object' && result !== null && 'action' in result; if (isValidResult(result)) { - expect(result.action).toBe('AppNotAuthenticated'); + return expect(result.action).toBe('AppNotAuthenticated'); } else { throw new Error('Unexpected result structure'); } diff --git a/tests/setupFlow.ts b/tests/setupFlow.ts index 61ae4ab..6271256 100644 --- a/tests/setupFlow.ts +++ b/tests/setupFlow.ts @@ -134,6 +134,6 @@ export default async function setupFlowTest(browser: Browser, EXTENSION_ID: stri console.log('Verifying setup completion'); const setupCompleteText = await findTextOnSetupPage('Setup Complete'); - expect(setupCompleteText).toBeTruthy(); + return expect(setupCompleteText).toBeTruthy(); console.log('Setup flow test completed successfully'); } From 1a1d1e95e871cdf1aa2b9a291384fd5f6983fe91 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Wed, 17 Jul 2024 18:32:02 +0200 Subject: [PATCH 06/49] Fix description --- tests/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/index.test.ts b/tests/index.test.ts index da43e7d..fa8dfe2 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -36,7 +36,7 @@ afterAll(async () => { }); describe.sequential('End-to-End Tests for Extension and Client', () => { - it('should allow the client to interact with the extension after setup', async () => { + it('should not allow the client to interact with the extension before setup', async () => { await needsSetupTest(browser); }); it('verify setup flow works as expected', async () => { From 2b5d6024a8a7e81d6674e88bad8e525a4a3d0304 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Wed, 17 Jul 2024 19:32:52 +0200 Subject: [PATCH 07/49] Try to fix failing tests --- tests/index.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/index.test.ts b/tests/index.test.ts index fa8dfe2..6acf558 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -3,7 +3,7 @@ import { rm } from 'fs/promises'; import { Server } from 'http'; import { resolve } from 'path'; import type { Browser } from 'puppeteer'; -import { afterAll, beforeAll, describe, it } from 'vitest'; +import { afterAll, beforeAll, describe, expect, it } from 'vitest'; import clientInteractionTest from './clientInteraction'; import { launchBrowserWithExtension, startServer } from './helpers'; @@ -37,18 +37,18 @@ afterAll(async () => { describe.sequential('End-to-End Tests for Extension and Client', () => { it('should not allow the client to interact with the extension before setup', async () => { - await needsSetupTest(browser); + await expect(needsSetupTest(browser)).resolves.not.toThrow(); }); it('verify setup flow works as expected', async () => { if (!EXTENSION_ID) { throw new Error('EXTENSION_ID is not set'); } - await setupFlowTest(browser, EXTENSION_ID); + await expect(setupFlowTest(browser, EXTENSION_ID)).resolves.not.toThrow(); }, 10000); it('should allow the client to interact with the extension after setup', async () => { - await clientInteractionTest(browser); + await expect(clientInteractionTest(browser)).resolves.not.toThrow(); }, 10000); it('should prevent the malicious page from signing messages', async () => { - await preventSignatureFromOtherOrigin(browser); + await expect(preventSignatureFromOtherOrigin(browser)).resolves.not.toThrow(); }); }); From f50ee8c49b212e7d77783adbac67cf8d55e2d5e5 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Wed, 17 Jul 2024 19:40:19 +0200 Subject: [PATCH 08/49] Check errors --- tests/clientInteraction.ts | 2 +- tests/helpers.ts | 1 + tests/index.test.ts | 8 ++++---- tests/needsSetup.ts | 2 +- tests/preventSignatureFromOtherOrigin.ts | 2 +- tests/setupFlow.ts | 2 +- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/clientInteraction.ts b/tests/clientInteraction.ts index 3f8445a..5a7c88a 100644 --- a/tests/clientInteraction.ts +++ b/tests/clientInteraction.ts @@ -96,5 +96,5 @@ export default async function clientInteractionTest(browser: Browser) { const result = validateSignature(pubKey, signedMessage, new Uint8Array(JSON.parse(messageInput))); - return expect(result).toBe(true); + expect(result).toBe(true); } diff --git a/tests/helpers.ts b/tests/helpers.ts index d5a3ba6..17fe063 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -8,6 +8,7 @@ import { vi } from 'vitest'; export const launchBrowserWithExtension = async (extensionPath: string): Promise => { return launch({ + dumpio: true, headless: true, args: [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`] }); diff --git a/tests/index.test.ts b/tests/index.test.ts index 6acf558..f4551fe 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -37,18 +37,18 @@ afterAll(async () => { describe.sequential('End-to-End Tests for Extension and Client', () => { it('should not allow the client to interact with the extension before setup', async () => { - await expect(needsSetupTest(browser)).resolves.not.toThrow(); + expect(await needsSetupTest(browser)).resolves.not.toThrow(); }); it('verify setup flow works as expected', async () => { if (!EXTENSION_ID) { throw new Error('EXTENSION_ID is not set'); } - await expect(setupFlowTest(browser, EXTENSION_ID)).resolves.not.toThrow(); + expect(await setupFlowTest(browser, EXTENSION_ID)).resolves.not.toThrow(); }, 10000); it('should allow the client to interact with the extension after setup', async () => { - await expect(clientInteractionTest(browser)).resolves.not.toThrow(); + expect(await clientInteractionTest(browser)).resolves.not.toThrow(); }, 10000); it('should prevent the malicious page from signing messages', async () => { - await expect(preventSignatureFromOtherOrigin(browser)).resolves.not.toThrow(); + expect(await preventSignatureFromOtherOrigin(browser)).resolves.not.toThrow(); }); }); diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index a32bc8b..b8d41d1 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -15,5 +15,5 @@ export default async function needsSetupTest(browser: Browser) { await signUpButton.click(); const needsSetupText = await findTextOnPage('NeedsSetup'); - return expect(needsSetupText).toBeTruthy(); + expect(needsSetupText).toBeTruthy(); } diff --git a/tests/preventSignatureFromOtherOrigin.ts b/tests/preventSignatureFromOtherOrigin.ts index 35874cb..5ad7009 100644 --- a/tests/preventSignatureFromOtherOrigin.ts +++ b/tests/preventSignatureFromOtherOrigin.ts @@ -48,7 +48,7 @@ export default async function preventSignatureFromOtherOrigin(browser: Browser) typeof result === 'object' && result !== null && 'action' in result; if (isValidResult(result)) { - return expect(result.action).toBe('AppNotAuthenticated'); + expect(result.action).toBe('AppNotAuthenticated'); } else { throw new Error('Unexpected result structure'); } diff --git a/tests/setupFlow.ts b/tests/setupFlow.ts index 6271256..61ae4ab 100644 --- a/tests/setupFlow.ts +++ b/tests/setupFlow.ts @@ -134,6 +134,6 @@ export default async function setupFlowTest(browser: Browser, EXTENSION_ID: stri console.log('Verifying setup completion'); const setupCompleteText = await findTextOnSetupPage('Setup Complete'); - return expect(setupCompleteText).toBeTruthy(); + expect(setupCompleteText).toBeTruthy(); console.log('Setup flow test completed successfully'); } From f326abd793591a58dbb9026d9a749b02515d995a Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Wed, 17 Jul 2024 19:46:59 +0200 Subject: [PATCH 09/49] Increased timeout --- tests/index.test.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/tests/index.test.ts b/tests/index.test.ts index f4551fe..46b2386 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -3,7 +3,7 @@ import { rm } from 'fs/promises'; import { Server } from 'http'; import { resolve } from 'path'; import type { Browser } from 'puppeteer'; -import { afterAll, beforeAll, describe, expect, it } from 'vitest'; +import { afterAll, beforeAll, describe, it } from 'vitest'; import clientInteractionTest from './clientInteraction'; import { launchBrowserWithExtension, startServer } from './helpers'; @@ -37,18 +37,21 @@ afterAll(async () => { describe.sequential('End-to-End Tests for Extension and Client', () => { it('should not allow the client to interact with the extension before setup', async () => { - expect(await needsSetupTest(browser)).resolves.not.toThrow(); - }); + await needsSetupTest(browser); + }, 10000); + it('verify setup flow works as expected', async () => { if (!EXTENSION_ID) { throw new Error('EXTENSION_ID is not set'); } - expect(await setupFlowTest(browser, EXTENSION_ID)).resolves.not.toThrow(); - }, 10000); + await setupFlowTest(browser, EXTENSION_ID); + }, 20000); + it('should allow the client to interact with the extension after setup', async () => { - expect(await clientInteractionTest(browser)).resolves.not.toThrow(); - }, 10000); + await clientInteractionTest(browser); + }, 20000); + it('should prevent the malicious page from signing messages', async () => { - expect(await preventSignatureFromOtherOrigin(browser)).resolves.not.toThrow(); - }); + await preventSignatureFromOtherOrigin(browser); + }, 20000); }); From e44c8a11d94f1f4b32f5c3756162b6bd4083c11f Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 09:17:37 +0200 Subject: [PATCH 10/49] Cache to check test --- .github/workflows/extension-PR.yaml | 13 +++++++++++++ vitest.config.ts | 8 ++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.github/workflows/extension-PR.yaml b/.github/workflows/extension-PR.yaml index 517b9dc..b57d8a6 100644 --- a/.github/workflows/extension-PR.yaml +++ b/.github/workflows/extension-PR.yaml @@ -25,15 +25,28 @@ jobs: - name: Install dependencies run: pnpm install --no-frozen-lockfile + - name: Cache build + id: cache-build + uses: actions/cache@v3 + with: + path: | + holo-key-manager-extension/build + holo-key-manager-js-client/lib + key: ${{ runner.os }}-build-${{ hashFiles('**/package.json') }}-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-build- + - name: Run unit tests run: pnpm test working-directory: holo-key-manager-extension - name: Build extension + if: steps.cache-build.outputs.cache-hit != 'true' run: pnpm build working-directory: holo-key-manager-extension - name: Build and pack client + if: steps.cache-build.outputs.cache-hit != 'true' run: pnpm build working-directory: holo-key-manager-js-client diff --git a/vitest.config.ts b/vitest.config.ts index d68d91f..c92dd74 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,11 +1,15 @@ import path from 'path'; import { defineConfig } from 'vitest/config'; - export default defineConfig({ test: { globals: true, environment: 'node', - include: ['tests/**/*.test.ts'] + include: ['tests/**/*.test.ts'], + poolOptions: { + threads: { + singleThread: true + } + } }, resolve: { alias: { From 8c1e8d20f7e390251dd7f206675b48c35b33b9c2 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 09:22:12 +0200 Subject: [PATCH 11/49] Test ci --- .github/workflows/extension-PR.yaml | 2 +- tests/index.test.ts | 30 ++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/extension-PR.yaml b/.github/workflows/extension-PR.yaml index b57d8a6..684f904 100644 --- a/.github/workflows/extension-PR.yaml +++ b/.github/workflows/extension-PR.yaml @@ -45,7 +45,7 @@ jobs: run: pnpm build working-directory: holo-key-manager-extension - - name: Build and pack client + - name: Build client if: steps.cache-build.outputs.cache-hit != 'true' run: pnpm build working-directory: holo-key-manager-js-client diff --git a/tests/index.test.ts b/tests/index.test.ts index 46b2386..b63ab49 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -5,11 +5,11 @@ import { resolve } from 'path'; import type { Browser } from 'puppeteer'; import { afterAll, beforeAll, describe, it } from 'vitest'; -import clientInteractionTest from './clientInteraction'; +// import clientInteractionTest from './clientInteraction'; import { launchBrowserWithExtension, startServer } from './helpers'; import needsSetupTest from './needsSetup'; -import preventSignatureFromOtherOrigin from './preventSignatureFromOtherOrigin'; -import setupFlowTest from './setupFlow'; +// import preventSignatureFromOtherOrigin from './preventSignatureFromOtherOrigin'; +// import setupFlowTest from './setupFlow'; dotenv.config(); @@ -40,18 +40,18 @@ describe.sequential('End-to-End Tests for Extension and Client', () => { await needsSetupTest(browser); }, 10000); - it('verify setup flow works as expected', async () => { - if (!EXTENSION_ID) { - throw new Error('EXTENSION_ID is not set'); - } - await setupFlowTest(browser, EXTENSION_ID); - }, 20000); + // it('verify setup flow works as expected', async () => { + // if (!EXTENSION_ID) { + // throw new Error('EXTENSION_ID is not set'); + // } + // await setupFlowTest(browser, EXTENSION_ID); + // }, 20000); - it('should allow the client to interact with the extension after setup', async () => { - await clientInteractionTest(browser); - }, 20000); + // it('should allow the client to interact with the extension after setup', async () => { + // await clientInteractionTest(browser); + // }, 20000); - it('should prevent the malicious page from signing messages', async () => { - await preventSignatureFromOtherOrigin(browser); - }, 20000); + // it('should prevent the malicious page from signing messages', async () => { + // await preventSignatureFromOtherOrigin(browser); + // }, 20000); }); From 4a2dabc080c0c2c4f62ee303d1394589ce9f0b53 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 09:28:04 +0200 Subject: [PATCH 12/49] Test --- .github/workflows/extension-PR.yaml | 6 ++---- tests/index.test.ts | 23 +++++++++++++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/.github/workflows/extension-PR.yaml b/.github/workflows/extension-PR.yaml index 684f904..077fba9 100644 --- a/.github/workflows/extension-PR.yaml +++ b/.github/workflows/extension-PR.yaml @@ -27,14 +27,12 @@ jobs: - name: Cache build id: cache-build - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | holo-key-manager-extension/build holo-key-manager-js-client/lib - key: ${{ runner.os }}-build-${{ hashFiles('**/package.json') }}-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-build- + key: test-cache - name: Run unit tests run: pnpm test diff --git a/tests/index.test.ts b/tests/index.test.ts index b63ab49..da6ccbf 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -3,11 +3,11 @@ import { rm } from 'fs/promises'; import { Server } from 'http'; import { resolve } from 'path'; import type { Browser } from 'puppeteer'; -import { afterAll, beforeAll, describe, it } from 'vitest'; +import { afterAll, beforeAll, describe, expect, it } from 'vitest'; // import clientInteractionTest from './clientInteraction'; -import { launchBrowserWithExtension, startServer } from './helpers'; -import needsSetupTest from './needsSetup'; +import { findTextBySelector, launchBrowserWithExtension, startServer } from './helpers'; +// import needsSetupTest from './needsSetup'; // import preventSignatureFromOtherOrigin from './preventSignatureFromOtherOrigin'; // import setupFlowTest from './setupFlow'; @@ -37,9 +37,24 @@ afterAll(async () => { describe.sequential('End-to-End Tests for Extension and Client', () => { it('should not allow the client to interact with the extension before setup', async () => { - await needsSetupTest(browser); + const page = await browser.newPage(); + await page.goto('http://localhost:3000/tests/test.html'); + + const findTextOnPage = findTextBySelector(page); + + const signUpButton = await findTextOnPage('Sign Up'); + expect(signUpButton).toBeTruthy(); + + await signUpButton.click(); + + const needsSetupText = await findTextOnPage('NeedsSetup'); + expect(needsSetupText).toBeTruthy(); }, 10000); + // it('should not allow the client to interact with the extension before setup', async () => { + // await needsSetupTest(browser); + // }, 10000); + // it('verify setup flow works as expected', async () => { // if (!EXTENSION_ID) { // throw new Error('EXTENSION_ID is not set'); From c70baa9a2479a0a3b3656469e3eca464c7b179d2 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 09:34:44 +0200 Subject: [PATCH 13/49] Fix ports --- tests/clientInteraction.ts | 2 +- tests/helpers.ts | 8 +------- tests/index.test.ts | 4 ++-- tests/needsSetup.ts | 2 +- tests/preventSignatureFromOtherOrigin.ts | 4 ++-- 5 files changed, 7 insertions(+), 13 deletions(-) diff --git a/tests/clientInteraction.ts b/tests/clientInteraction.ts index 5a7c88a..000c555 100644 --- a/tests/clientInteraction.ts +++ b/tests/clientInteraction.ts @@ -11,7 +11,7 @@ import { export default async function clientInteractionTest(browser: Browser) { const appPage = await browser.newPage(); - await appPage.goto('http://localhost:3000/tests/test.html'); + await appPage.goto('http://localhost:5000/tests/test.html'); const findTextOnAppPage = findTextBySelector(appPage); diff --git a/tests/helpers.ts b/tests/helpers.ts index 17fe063..044d4c1 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -62,18 +62,12 @@ export const findButtonExtensionByText = (context: Page) => findElementByText(context, 'button:not(:disabled) > span'); export const findTextBySelector = (context: Page) => findElementByText(context, ''); -export const startServer = (port: number = 3000): Server => { +export const startServer = (port: number = 5000): Server => { const app = express(); app.use(express.static(resolve('./holo-key-manager-js-client'))); return app.listen(port); }; -export const startOtherServer = (): Server => { - const app = express(); - app.use(express.static(resolve('./holo-key-manager-js-client'))); - return app.listen(4000); -}; - export const waitForNewPage = (browser: Browser): Promise => new Promise((resolve, reject) => browser.once('targetcreated', async (target) => { diff --git a/tests/index.test.ts b/tests/index.test.ts index da6ccbf..fd47b99 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -35,10 +35,10 @@ afterAll(async () => { server.close(); }); -describe.sequential('End-to-End Tests for Extension and Client', () => { +describe('End-to-End Tests for Extension and Client', () => { it('should not allow the client to interact with the extension before setup', async () => { const page = await browser.newPage(); - await page.goto('http://localhost:3000/tests/test.html'); + await page.goto('http://localhost:5000/tests/test.html'); const findTextOnPage = findTextBySelector(page); diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index b8d41d1..7d3ceaa 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -5,7 +5,7 @@ import { findTextBySelector } from './helpers'; export default async function needsSetupTest(browser: Browser) { const page = await browser.newPage(); - await page.goto('http://localhost:3000/tests/test.html'); + await page.goto('http://localhost:5000/tests/test.html'); const findTextOnPage = findTextBySelector(page); diff --git a/tests/preventSignatureFromOtherOrigin.ts b/tests/preventSignatureFromOtherOrigin.ts index 5ad7009..0c28982 100644 --- a/tests/preventSignatureFromOtherOrigin.ts +++ b/tests/preventSignatureFromOtherOrigin.ts @@ -4,10 +4,10 @@ import { expect } from 'vitest'; import { startServer } from './helpers'; export default async function preventSignatureFromOtherOrigin(browser: Browser) { - const server = startServer(4000); + const server = startServer(6000); const maliciousPage = await browser.newPage(); - await maliciousPage.goto('http://localhost:4000'); + await maliciousPage.goto('http://localhost:6000'); try { const result = await maliciousPage.evaluate(async () => { From 23a81d4624bcdc5426d7f61bd0f12c5529f1aca1 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 09:36:36 +0200 Subject: [PATCH 14/49] Fix ports --- tests/clientInteraction.ts | 2 +- tests/helpers.ts | 2 +- tests/index.test.ts | 2 +- tests/needsSetup.ts | 2 +- tests/preventSignatureFromOtherOrigin.ts | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/clientInteraction.ts b/tests/clientInteraction.ts index 000c555..f8b4c6c 100644 --- a/tests/clientInteraction.ts +++ b/tests/clientInteraction.ts @@ -11,7 +11,7 @@ import { export default async function clientInteractionTest(browser: Browser) { const appPage = await browser.newPage(); - await appPage.goto('http://localhost:5000/tests/test.html'); + await appPage.goto('http://localhost:3007/tests/test.html'); const findTextOnAppPage = findTextBySelector(appPage); diff --git a/tests/helpers.ts b/tests/helpers.ts index 044d4c1..1072d5f 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -62,7 +62,7 @@ export const findButtonExtensionByText = (context: Page) => findElementByText(context, 'button:not(:disabled) > span'); export const findTextBySelector = (context: Page) => findElementByText(context, ''); -export const startServer = (port: number = 5000): Server => { +export const startServer = (port: number = 3007): Server => { const app = express(); app.use(express.static(resolve('./holo-key-manager-js-client'))); return app.listen(port); diff --git a/tests/index.test.ts b/tests/index.test.ts index fd47b99..6808b0d 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -38,7 +38,7 @@ afterAll(async () => { describe('End-to-End Tests for Extension and Client', () => { it('should not allow the client to interact with the extension before setup', async () => { const page = await browser.newPage(); - await page.goto('http://localhost:5000/tests/test.html'); + await page.goto('http://localhost:3007/tests/test.html'); const findTextOnPage = findTextBySelector(page); diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index 7d3ceaa..533b21a 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -5,7 +5,7 @@ import { findTextBySelector } from './helpers'; export default async function needsSetupTest(browser: Browser) { const page = await browser.newPage(); - await page.goto('http://localhost:5000/tests/test.html'); + await page.goto('http://localhost:3007/tests/test.html'); const findTextOnPage = findTextBySelector(page); diff --git a/tests/preventSignatureFromOtherOrigin.ts b/tests/preventSignatureFromOtherOrigin.ts index 0c28982..327ad02 100644 --- a/tests/preventSignatureFromOtherOrigin.ts +++ b/tests/preventSignatureFromOtherOrigin.ts @@ -4,10 +4,10 @@ import { expect } from 'vitest'; import { startServer } from './helpers'; export default async function preventSignatureFromOtherOrigin(browser: Browser) { - const server = startServer(6000); + const server = startServer(3008); const maliciousPage = await browser.newPage(); - await maliciousPage.goto('http://localhost:6000'); + await maliciousPage.goto('http://localhost:3008'); try { const result = await maliciousPage.evaluate(async () => { From db394603d6ea550416c23875f7e762973e260293 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 09:38:50 +0200 Subject: [PATCH 15/49] Check tests --- tests/index.test.ts | 61 +++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 38 deletions(-) diff --git a/tests/index.test.ts b/tests/index.test.ts index 6808b0d..778163a 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -3,13 +3,13 @@ import { rm } from 'fs/promises'; import { Server } from 'http'; import { resolve } from 'path'; import type { Browser } from 'puppeteer'; -import { afterAll, beforeAll, describe, expect, it } from 'vitest'; +import { afterAll, beforeAll, describe, it } from 'vitest'; -// import clientInteractionTest from './clientInteraction'; -import { findTextBySelector, launchBrowserWithExtension, startServer } from './helpers'; -// import needsSetupTest from './needsSetup'; -// import preventSignatureFromOtherOrigin from './preventSignatureFromOtherOrigin'; -// import setupFlowTest from './setupFlow'; +import clientInteractionTest from './clientInteraction'; +import { launchBrowserWithExtension, startServer } from './helpers'; +import needsSetupTest from './needsSetup'; +import preventSignatureFromOtherOrigin from './preventSignatureFromOtherOrigin'; +import setupFlowTest from './setupFlow'; dotenv.config(); @@ -37,36 +37,21 @@ afterAll(async () => { describe('End-to-End Tests for Extension and Client', () => { it('should not allow the client to interact with the extension before setup', async () => { - const page = await browser.newPage(); - await page.goto('http://localhost:3007/tests/test.html'); - - const findTextOnPage = findTextBySelector(page); - - const signUpButton = await findTextOnPage('Sign Up'); - expect(signUpButton).toBeTruthy(); - - await signUpButton.click(); - - const needsSetupText = await findTextOnPage('NeedsSetup'); - expect(needsSetupText).toBeTruthy(); - }, 10000); - - // it('should not allow the client to interact with the extension before setup', async () => { - // await needsSetupTest(browser); - // }, 10000); - - // it('verify setup flow works as expected', async () => { - // if (!EXTENSION_ID) { - // throw new Error('EXTENSION_ID is not set'); - // } - // await setupFlowTest(browser, EXTENSION_ID); - // }, 20000); - - // it('should allow the client to interact with the extension after setup', async () => { - // await clientInteractionTest(browser); - // }, 20000); - - // it('should prevent the malicious page from signing messages', async () => { - // await preventSignatureFromOtherOrigin(browser); - // }, 20000); + await needsSetupTest(browser); + }); + + it('verify setup flow works as expected', async () => { + if (!EXTENSION_ID) { + throw new Error('EXTENSION_ID is not set'); + } + await setupFlowTest(browser, EXTENSION_ID); + }); + + it('should allow the client to interact with the extension after setup', async () => { + await clientInteractionTest(browser); + }); + + it('should prevent the malicious page from signing messages', async () => { + await preventSignatureFromOtherOrigin(browser); + }); }); From 820872fe0915485ed77207598639174e3d23ea47 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 09:43:16 +0200 Subject: [PATCH 16/49] Add more flags --- tests/helpers.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/helpers.ts b/tests/helpers.ts index 1072d5f..4af8e60 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -10,7 +10,12 @@ export const launchBrowserWithExtension = async (extensionPath: string): Promise return launch({ dumpio: true, headless: true, - args: [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`] + args: [ + `--disable-extensions-except=${extensionPath}`, + `--load-extension=${extensionPath}`, + '--no-sandbox', + '--disable-setuid-sandbox' + ] }); }; From dc8ec0cb30c77370b5b6071c7bd1b24c1b27a869 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 09:51:50 +0200 Subject: [PATCH 17/49] Check test --- tests/helpers.ts | 7 +------ tests/index.test.ts | 13 ++++++++----- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/tests/helpers.ts b/tests/helpers.ts index 4af8e60..1072d5f 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -10,12 +10,7 @@ export const launchBrowserWithExtension = async (extensionPath: string): Promise return launch({ dumpio: true, headless: true, - args: [ - `--disable-extensions-except=${extensionPath}`, - `--load-extension=${extensionPath}`, - '--no-sandbox', - '--disable-setuid-sandbox' - ] + args: [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`] }); }; diff --git a/tests/index.test.ts b/tests/index.test.ts index 778163a..afa2456 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,12 +1,15 @@ import dotenv from 'dotenv'; import { rm } from 'fs/promises'; -import { Server } from 'http'; +// import { Server } from 'http'; import { resolve } from 'path'; import type { Browser } from 'puppeteer'; import { afterAll, beforeAll, describe, it } from 'vitest'; import clientInteractionTest from './clientInteraction'; -import { launchBrowserWithExtension, startServer } from './helpers'; +import { + launchBrowserWithExtension + // startServer +} from './helpers'; import needsSetupTest from './needsSetup'; import preventSignatureFromOtherOrigin from './preventSignatureFromOtherOrigin'; import setupFlowTest from './setupFlow'; @@ -18,7 +21,7 @@ const EXTENSION_ID = process.env.CHROME_ID; const downloadPath = resolve('./downloads'); let browser: Browser; -let server: Server; +// let server: Server; beforeAll(async () => { if (!EXTENSION_ID) { @@ -26,13 +29,13 @@ beforeAll(async () => { } const extensionPath = resolve('holo-key-manager-extension', 'build'); browser = await launchBrowserWithExtension(extensionPath); - server = startServer(); + // server = startServer(); }); afterAll(async () => { await rm(downloadPath, { recursive: true, force: true }); await browser?.close(); - server.close(); + // server.close(); }); describe('End-to-End Tests for Extension and Client', () => { From a6003fb00fe0ad0c0e964fbd342674e8fcc9daeb Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 09:53:05 +0200 Subject: [PATCH 18/49] Check test --- tests/index.test.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/index.test.ts b/tests/index.test.ts index afa2456..76d0ab0 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -5,13 +5,13 @@ import { resolve } from 'path'; import type { Browser } from 'puppeteer'; import { afterAll, beforeAll, describe, it } from 'vitest'; -import clientInteractionTest from './clientInteraction'; +// import clientInteractionTest from './clientInteraction'; import { launchBrowserWithExtension // startServer } from './helpers'; -import needsSetupTest from './needsSetup'; -import preventSignatureFromOtherOrigin from './preventSignatureFromOtherOrigin'; +// import needsSetupTest from './needsSetup'; +// import preventSignatureFromOtherOrigin from './preventSignatureFromOtherOrigin'; import setupFlowTest from './setupFlow'; dotenv.config(); @@ -39,9 +39,9 @@ afterAll(async () => { }); describe('End-to-End Tests for Extension and Client', () => { - it('should not allow the client to interact with the extension before setup', async () => { - await needsSetupTest(browser); - }); + // it('should not allow the client to interact with the extension before setup', async () => { + // await needsSetupTest(browser); + // }); it('verify setup flow works as expected', async () => { if (!EXTENSION_ID) { @@ -50,11 +50,11 @@ describe('End-to-End Tests for Extension and Client', () => { await setupFlowTest(browser, EXTENSION_ID); }); - it('should allow the client to interact with the extension after setup', async () => { - await clientInteractionTest(browser); - }); + // it('should allow the client to interact with the extension after setup', async () => { + // await clientInteractionTest(browser); + // }); - it('should prevent the malicious page from signing messages', async () => { - await preventSignatureFromOtherOrigin(browser); - }); + // it('should prevent the malicious page from signing messages', async () => { + // await preventSignatureFromOtherOrigin(browser); + // }); }); From 4ea8cd7d8573aa78b4a044f2b93b6aa72c990f54 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 10:37:35 +0200 Subject: [PATCH 19/49] Add express server start --- package.json | 1 + tests/helpers.ts | 10 +++++++--- tests/index.test.ts | 13 +++++-------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 9947230..c60b117 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "prepare": "husky install", "test": "concurrently \"pnpm e2e-tests\" \"cd holo-key-manager-extension && pnpm test\" \"cd holo-key-manager-js-client && pnpm test\"", "e2e-tests": "vitest run" + }, "devDependencies": { "@rollup/plugin-node-resolve": "^15.2.3", diff --git a/tests/helpers.ts b/tests/helpers.ts index 1072d5f..1491e3b 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -63,9 +63,13 @@ export const findButtonExtensionByText = (context: Page) => export const findTextBySelector = (context: Page) => findElementByText(context, ''); export const startServer = (port: number = 3007): Server => { - const app = express(); - app.use(express.static(resolve('./holo-key-manager-js-client'))); - return app.listen(port); + try { + const app = express(); + app.use(express.static(resolve('./holo-key-manager-js-client'))); + return app.listen(port); + } catch (error) { + throw new Error(`Failed to start server: ${error}`); + } }; export const waitForNewPage = (browser: Browser): Promise => diff --git a/tests/index.test.ts b/tests/index.test.ts index 76d0ab0..9b2ea3f 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,15 +1,12 @@ import dotenv from 'dotenv'; import { rm } from 'fs/promises'; -// import { Server } from 'http'; +import { Server } from 'http'; import { resolve } from 'path'; import type { Browser } from 'puppeteer'; import { afterAll, beforeAll, describe, it } from 'vitest'; // import clientInteractionTest from './clientInteraction'; -import { - launchBrowserWithExtension - // startServer -} from './helpers'; +import { launchBrowserWithExtension, startServer } from './helpers'; // import needsSetupTest from './needsSetup'; // import preventSignatureFromOtherOrigin from './preventSignatureFromOtherOrigin'; import setupFlowTest from './setupFlow'; @@ -21,7 +18,7 @@ const EXTENSION_ID = process.env.CHROME_ID; const downloadPath = resolve('./downloads'); let browser: Browser; -// let server: Server; +let server: Server; beforeAll(async () => { if (!EXTENSION_ID) { @@ -29,13 +26,13 @@ beforeAll(async () => { } const extensionPath = resolve('holo-key-manager-extension', 'build'); browser = await launchBrowserWithExtension(extensionPath); - // server = startServer(); + server = startServer(); }); afterAll(async () => { await rm(downloadPath, { recursive: true, force: true }); await browser?.close(); - // server.close(); + server.close(); }); describe('End-to-End Tests for Extension and Client', () => { From c8edc45660a268b818c259a1f09d2440e9ebcbcd Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 10:40:33 +0200 Subject: [PATCH 20/49] Add needs setup test --- tests/index.test.ts | 7 ++++--- tests/setupFlow.ts | 24 +----------------------- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/tests/index.test.ts b/tests/index.test.ts index 9b2ea3f..4a91ca6 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -7,6 +7,7 @@ import { afterAll, beforeAll, describe, it } from 'vitest'; // import clientInteractionTest from './clientInteraction'; import { launchBrowserWithExtension, startServer } from './helpers'; +import needsSetupTest from './needsSetup'; // import needsSetupTest from './needsSetup'; // import preventSignatureFromOtherOrigin from './preventSignatureFromOtherOrigin'; import setupFlowTest from './setupFlow'; @@ -36,9 +37,9 @@ afterAll(async () => { }); describe('End-to-End Tests for Extension and Client', () => { - // it('should not allow the client to interact with the extension before setup', async () => { - // await needsSetupTest(browser); - // }); + it('should not allow the client to interact with the extension before setup', async () => { + await needsSetupTest(browser); + }); it('verify setup flow works as expected', async () => { if (!EXTENSION_ID) { diff --git a/tests/setupFlow.ts b/tests/setupFlow.ts index 61ae4ab..7d633bf 100644 --- a/tests/setupFlow.ts +++ b/tests/setupFlow.ts @@ -18,109 +18,89 @@ export default async function setupFlowTest(browser: Browser, EXTENSION_ID: stri if (!EXTENSION_ID) { throw new Error('EXTENSION_ID is not set'); } - console.log('Starting setup flow test'); + const page = await openExtensionPage(browser, EXTENSION_ID); - console.log('Finding setup button'); const setupButton = await findButtonExtensionByText(page)('Setup'); - console.log('Checking for setup page content'); const setupPageContent = await findTextBySelector(page)('Setup Required'); expect(setupPageContent).toBeTruthy(); - console.log('Clicking setup button and waiting for new page'); const setupPage = await clickButtonAndWaitForNewPage(browser, setupButton, downloadPath); const findButtonOnSetupPage = findButtonExtensionByText(setupPage); const findTextOnSetupPage = findTextBySelector(setupPage); - console.log('Verifying setup page text'); const setupPageText = await findTextOnSetupPage( 'Holo Key Manager is a safe place to set up and manage keys for Holochain apps' ); expect(setupPageText).toBeTruthy(); - console.log('Clicking first time setup button'); const firstTimeSetupButton = await findButtonOnSetupPage('First time set up'); await Promise.all([setupPage.waitForNavigation(), firstTimeSetupButton.click()]); - console.log('Verifying password setup page'); const setKeyManagerPasswordText = await findTextOnSetupPage('Set Key Manager Password'); expect(setKeyManagerPasswordText).toBeTruthy(); - console.log('Entering password'); await setupPage.type('input[id*="enter-password"]', 'password'); await setupPage.type('input[id="confirm-password"]', 'password'); - console.log('Setting password'); const setPasswordButton = await findButtonOnSetupPage('Set password'); await Promise.all([setupPage.waitForNavigation(), setPasswordButton.click()]); - console.log('Clicking "I understand" button'); const iUnderstandButton = await findButtonOnSetupPage('I understand'); expect(iUnderstandButton).toBeTruthy(); await Promise.all([setupPage.waitForNavigation(), iUnderstandButton.click()]); - console.log('Verifying passphrase entry page'); const enterPassphraseText = await findTextOnSetupPage('Enter Passphrase'); expect(enterPassphraseText).toBeTruthy(); - console.log('Entering passphrase'); await setupPage.type('textarea[placeholder="Enter Passphrase"]', 'passphrase passphrase'); - console.log('Setting passphrase'); const setPassphraseButton = await findButtonOnSetupPage('Set passphrase'); await setPassphraseButton.click(); - console.log('Verifying passphrase confirmation page'); const confirmPassphraseText = await findTextOnSetupPage('Confirm Passphrase'); expect(confirmPassphraseText).toBeTruthy(); - console.log('Confirming passphrase'); await setupPage.type('textarea[placeholder="Confirm Passphrase"]', 'passphrase passphrase'); const confirmPassphraseButton = await findButtonOnSetupPage('Next'); await Promise.all([setupPage.waitForNavigation(), confirmPassphraseButton.click()]); - console.log('Verifying seed generation page'); const generateSeedText = await findTextOnSetupPage('Generate seed and key files'); expect(generateSeedText).toBeTruthy(); - console.log('Generating seed'); const generateSeedButton = await findButtonOnSetupPage('Generate'); await Promise.all([setupPage.waitForNavigation(), generateSeedButton.click()]); - console.log('Verifying seed saving page'); const saveSeedText = await findTextOnSetupPage('Save seed and key files'); expect(saveSeedText).toBeTruthy(); - console.log('Saving seed and key files'); const exportButton = await findButtonOnSetupPage('Save'); exportButton.click(); - console.log('Verifying downloaded keys file'); const keysFilePath = join(downloadPath, 'keys.zip'); const keysFileExists = await fileExists(keysFilePath); expect(keysFileExists).toBe(true); - console.log('Checking contents of keys file'); const zipContent = await readFile(keysFilePath); const zip = await JSZip.loadAsync(zipContent); @@ -131,9 +111,7 @@ export default async function setupFlowTest(browser: Browser, EXTENSION_ID: stri expect(actualFiles).toContain(file); }); - console.log('Verifying setup completion'); const setupCompleteText = await findTextOnSetupPage('Setup Complete'); expect(setupCompleteText).toBeTruthy(); - console.log('Setup flow test completed successfully'); } From fc04a011a6ca08ca6d51f607dc5bc93baa77ee46 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 10:49:15 +0200 Subject: [PATCH 21/49] Show content --- tests/needsSetup.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index 533b21a..56fd2be 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -7,6 +7,8 @@ export default async function needsSetupTest(browser: Browser) { const page = await browser.newPage(); await page.goto('http://localhost:3007/tests/test.html'); + console.log(await page.content()); + const findTextOnPage = findTextBySelector(page); const signUpButton = await findTextOnPage('Sign Up'); From 0964c9e96190de2f686e9cb4db1c876841fd98a1 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 10:55:08 +0200 Subject: [PATCH 22/49] Test --- tests/needsSetup.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index 56fd2be..677c677 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -1,7 +1,7 @@ import { Browser } from 'puppeteer'; import { expect } from 'vitest'; -import { findTextBySelector } from './helpers'; +// import { findTextBySelector } from './helpers'; export default async function needsSetupTest(browser: Browser) { const page = await browser.newPage(); @@ -9,13 +9,15 @@ export default async function needsSetupTest(browser: Browser) { console.log(await page.content()); - const findTextOnPage = findTextBySelector(page); + expect(page).toBeTruthy(); - const signUpButton = await findTextOnPage('Sign Up'); - expect(signUpButton).toBeTruthy(); + // const findTextOnPage = findTextBySelector(page); - await signUpButton.click(); + // const signUpButton = await findTextOnPage('Sign Up'); + // expect(signUpButton).toBeTruthy(); - const needsSetupText = await findTextOnPage('NeedsSetup'); - expect(needsSetupText).toBeTruthy(); + // await signUpButton.click(); + + // const needsSetupText = await findTextOnPage('NeedsSetup'); + // expect(needsSetupText).toBeTruthy(); } From ffc09c4ccffe4b721cd53ee80f2af4e13b8ccdd1 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 12:02:43 +0200 Subject: [PATCH 23/49] Test next step --- tests/needsSetup.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index 677c677..8c4ae5c 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -1,6 +1,8 @@ import { Browser } from 'puppeteer'; import { expect } from 'vitest'; +import { findTextBySelector } from './helpers'; + // import { findTextBySelector } from './helpers'; export default async function needsSetupTest(browser: Browser) { @@ -9,12 +11,12 @@ export default async function needsSetupTest(browser: Browser) { console.log(await page.content()); - expect(page).toBeTruthy(); + const findTextOnPage = findTextBySelector(page); - // const findTextOnPage = findTextBySelector(page); + const signUpButton = await findTextOnPage('Sign Up'); + expect(signUpButton).toBeTruthy(); - // const signUpButton = await findTextOnPage('Sign Up'); - // expect(signUpButton).toBeTruthy(); + expect(page).toBeTruthy(); // await signUpButton.click(); From 00a20cb5d1556c093dbae5c64250dc754b720b8b Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 12:03:56 +0200 Subject: [PATCH 24/49] Test next step --- tests/needsSetup.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index 8c4ae5c..775ae05 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -9,8 +9,6 @@ export default async function needsSetupTest(browser: Browser) { const page = await browser.newPage(); await page.goto('http://localhost:3007/tests/test.html'); - console.log(await page.content()); - const findTextOnPage = findTextBySelector(page); const signUpButton = await findTextOnPage('Sign Up'); @@ -18,8 +16,10 @@ export default async function needsSetupTest(browser: Browser) { expect(page).toBeTruthy(); - // await signUpButton.click(); + await signUpButton.click(); + + console.log(await page.content()); - // const needsSetupText = await findTextOnPage('NeedsSetup'); - // expect(needsSetupText).toBeTruthy(); + const needsSetupText = await findTextOnPage('NeedsSetup'); + expect(needsSetupText).toBeTruthy(); } From 409b0b46651d8a8c02523fec1ce852726f543905 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 12:05:59 +0200 Subject: [PATCH 25/49] Test next step --- tests/needsSetup.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index 775ae05..c592e67 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -18,7 +18,10 @@ export default async function needsSetupTest(browser: Browser) { await signUpButton.click(); - console.log(await page.content()); + await new Promise((resolve) => setTimeout(resolve, 2000)); + + const pageContent = await page.content(); + console.log(pageContent); const needsSetupText = await findTextOnPage('NeedsSetup'); expect(needsSetupText).toBeTruthy(); From d6115b80eb64e76edd4951319195ef4d37d95a2b Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 12:08:56 +0200 Subject: [PATCH 26/49] Test step --- holo-key-manager-js-client/tests/test.html | 2 ++ tests/needsSetup.ts | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/holo-key-manager-js-client/tests/test.html b/holo-key-manager-js-client/tests/test.html index 9606510..34f5268 100644 --- a/holo-key-manager-js-client/tests/test.html +++ b/holo-key-manager-js-client/tests/test.html @@ -21,9 +21,11 @@ document.getElementById(buttonId).addEventListener('click', async () => { const resultElement = document.getElementById(`${buttonId}Result`); try { + console.log('Action:', action); const result = await action(); resultElement.textContent = `${buttonId} successful: ${JSON.stringify(result)}`; } catch (error) { + console.log('Error:', error); resultElement.textContent = `Error: ${error.message}`; } }); diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index c592e67..a2324e6 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -8,6 +8,11 @@ import { findTextBySelector } from './helpers'; export default async function needsSetupTest(browser: Browser) { const page = await browser.newPage(); await page.goto('http://localhost:3007/tests/test.html'); + page.on('console', (msg) => { + for (let i = 0; i < msg.args().length; ++i) { + console.log(`${i}: ${msg.args()[i]}`); + } + }); const findTextOnPage = findTextBySelector(page); From db685033b3e7a2dceae489a6cb92574cbab74062 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 13:09:58 +0200 Subject: [PATCH 27/49] Show browser version --- tests/index.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/index.test.ts b/tests/index.test.ts index 4a91ca6..b0b7d9c 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -14,7 +14,7 @@ import setupFlowTest from './setupFlow'; dotenv.config(); -const EXTENSION_ID = process.env.CHROME_ID; +const EXTENSION_ID = process.env.CHROME_ID || 'eggfhkdnfdhdpmkfpihjjbnncgmhihce'; const downloadPath = resolve('./downloads'); @@ -27,6 +27,8 @@ beforeAll(async () => { } const extensionPath = resolve('holo-key-manager-extension', 'build'); browser = await launchBrowserWithExtension(extensionPath); + const version = await browser.version(); + console.log('Browser version:', version); server = startServer(); }); From 08231c5a1c77a5e5199b8765fd80af078f07f029 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 14:04:30 +0200 Subject: [PATCH 28/49] Check console logs --- tests/index.test.ts | 2 -- tests/needsSetup.ts | 24 +++++++++++++++--------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/tests/index.test.ts b/tests/index.test.ts index b0b7d9c..411a6ca 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -27,8 +27,6 @@ beforeAll(async () => { } const extensionPath = resolve('holo-key-manager-extension', 'build'); browser = await launchBrowserWithExtension(extensionPath); - const version = await browser.version(); - console.log('Browser version:', version); server = startServer(); }); diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index a2324e6..ccedfc0 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -8,10 +8,21 @@ import { findTextBySelector } from './helpers'; export default async function needsSetupTest(browser: Browser) { const page = await browser.newPage(); await page.goto('http://localhost:3007/tests/test.html'); - page.on('console', (msg) => { - for (let i = 0; i < msg.args().length; ++i) { - console.log(`${i}: ${msg.args()[i]}`); - } + + await page.evaluate(() => { + window.addEventListener('message', (event) => { + console.log(event.data); + }); + }); + page.on('console', async (message) => { + const type = message.type(); + const text = await message.text(); + const args = await Promise.all(message.args().map((arg) => arg.jsonValue())); + + const formattedArgs = args.map((arg) => JSON.stringify(arg)).join(', '); + console.log( + `Console message [${type}]: ${text}${formattedArgs ? ` | Args: ${formattedArgs}` : ''}` + ); }); const findTextOnPage = findTextBySelector(page); @@ -23,11 +34,6 @@ export default async function needsSetupTest(browser: Browser) { await signUpButton.click(); - await new Promise((resolve) => setTimeout(resolve, 2000)); - - const pageContent = await page.content(); - console.log(pageContent); - const needsSetupText = await findTextOnPage('NeedsSetup'); expect(needsSetupText).toBeTruthy(); } From f94fe501f917f9ff0b8d41ee45efd394c69776e5 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 14:13:57 +0200 Subject: [PATCH 29/49] Test --- holo-key-manager-extension/scripts/content.ts | 1 + tests/needsSetup.ts | 10 ++++++++++ tests/setupFlow.ts | 10 ++++++++++ 3 files changed, 21 insertions(+) diff --git a/holo-key-manager-extension/scripts/content.ts b/holo-key-manager-extension/scripts/content.ts index edfbf89..8e6957f 100644 --- a/holo-key-manager-extension/scripts/content.ts +++ b/holo-key-manager-extension/scripts/content.ts @@ -7,6 +7,7 @@ const parseAndHandleMessage = async (event: MessageEvent) => { const parsedResult = MessageWithIdSchema.safeParse(event.data); if (!parsedResult.success || parsedResult.data.sender === SENDER_BACKGROUND_SCRIPT) return; try { + console.log('Sending message to background script'); const response = await sendMessage({ ...parsedResult.data, origin: event.origin }); const parsedMessageSchema = parseMessageSchema(response); window.postMessage(responseToMessage(parsedMessageSchema.data, parsedResult.data.id), '*'); diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index ccedfc0..4882248 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -9,6 +9,16 @@ export default async function needsSetupTest(browser: Browser) { const page = await browser.newPage(); await page.goto('http://localhost:3007/tests/test.html'); + const targets = browser.targets(); + console.log(targets); + const serviceWorkerTarget = targets.find((target) => target.type() === 'service_worker'); + + if (serviceWorkerTarget) { + console.log('Service worker from this extension is working'); + } else { + console.log('Service worker from this extension is not detected'); + } + await page.evaluate(() => { window.addEventListener('message', (event) => { console.log(event.data); diff --git a/tests/setupFlow.ts b/tests/setupFlow.ts index 7d633bf..f5d5ce0 100644 --- a/tests/setupFlow.ts +++ b/tests/setupFlow.ts @@ -21,6 +21,16 @@ export default async function setupFlowTest(browser: Browser, EXTENSION_ID: stri const page = await openExtensionPage(browser, EXTENSION_ID); + const targets = browser.targets(); + console.log(targets); + const serviceWorkerTarget = targets.find((target) => target.type() === 'service_worker'); + + if (serviceWorkerTarget) { + console.log('Service worker from this extension is working'); + } else { + console.log('Service worker from this extension is not detected'); + } + const setupButton = await findButtonExtensionByText(page)('Setup'); const setupPageContent = await findTextBySelector(page)('Setup Required'); From d7b45599cb5adeb8f6d0672c699e358c7c6aabef Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 14:30:19 +0200 Subject: [PATCH 30/49] Test in ci --- holo-key-manager-extension/scripts/background.ts | 1 + holo-key-manager-extension/scripts/content.ts | 5 ++++- tests/needsSetup.ts | 8 +------- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/holo-key-manager-extension/scripts/background.ts b/holo-key-manager-extension/scripts/background.ts index 3c8f4bb..03f9482 100644 --- a/holo-key-manager-extension/scripts/background.ts +++ b/holo-key-manager-extension/scripts/background.ts @@ -196,6 +196,7 @@ const processMessageExtension = async ( }; chrome.runtime.onMessage.addListener((message: Message, sender, sendResponse: SendResponse) => { + console.log('Received message from', sender); const sendResponseWithSender = (response: ActionPayload) => sendResponse({ ...response, sender: SENDER_BACKGROUND_SCRIPT }); diff --git a/holo-key-manager-extension/scripts/content.ts b/holo-key-manager-extension/scripts/content.ts index 8e6957f..94c8cac 100644 --- a/holo-key-manager-extension/scripts/content.ts +++ b/holo-key-manager-extension/scripts/content.ts @@ -7,7 +7,10 @@ const parseAndHandleMessage = async (event: MessageEvent) => { const parsedResult = MessageWithIdSchema.safeParse(event.data); if (!parsedResult.success || parsedResult.data.sender === SENDER_BACKGROUND_SCRIPT) return; try { - console.log('Sending message to background script'); + window.postMessage('Sending message to background script', '*'); + window.postMessage(JSON.stringify(chrome), '*'); + window.postMessage(JSON.stringify(chrome.runtime), '*'); + window.postMessage(JSON.stringify(chrome.runtime.sendMessage), '*'); const response = await sendMessage({ ...parsedResult.data, origin: event.origin }); const parsedMessageSchema = parseMessageSchema(response); window.postMessage(responseToMessage(parsedMessageSchema.data, parsedResult.data.id), '*'); diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index 4882248..67274ae 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -11,19 +11,13 @@ export default async function needsSetupTest(browser: Browser) { const targets = browser.targets(); console.log(targets); - const serviceWorkerTarget = targets.find((target) => target.type() === 'service_worker'); - - if (serviceWorkerTarget) { - console.log('Service worker from this extension is working'); - } else { - console.log('Service worker from this extension is not detected'); - } await page.evaluate(() => { window.addEventListener('message', (event) => { console.log(event.data); }); }); + page.on('console', async (message) => { const type = message.type(); const text = await message.text(); From 636cdb08da750ecca4833835d534fd5c7bea0e24 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 14:30:41 +0200 Subject: [PATCH 31/49] Change cache --- .github/workflows/extension-PR.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/extension-PR.yaml b/.github/workflows/extension-PR.yaml index 077fba9..5e39094 100644 --- a/.github/workflows/extension-PR.yaml +++ b/.github/workflows/extension-PR.yaml @@ -32,7 +32,7 @@ jobs: path: | holo-key-manager-extension/build holo-key-manager-js-client/lib - key: test-cache + key: test-cache-1 - name: Run unit tests run: pnpm test From ee814bcccf3e4ebfb090d4377581ddf3a8b36ae8 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 14:47:55 +0200 Subject: [PATCH 32/49] Test code --- .../scripts/background.ts | 2 +- holo-key-manager-extension/scripts/content.ts | 4 ---- tests/needsSetup.ts | 17 +++++++++++++++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/holo-key-manager-extension/scripts/background.ts b/holo-key-manager-extension/scripts/background.ts index 03f9482..594f17b 100644 --- a/holo-key-manager-extension/scripts/background.ts +++ b/holo-key-manager-extension/scripts/background.ts @@ -196,7 +196,7 @@ const processMessageExtension = async ( }; chrome.runtime.onMessage.addListener((message: Message, sender, sendResponse: SendResponse) => { - console.log('Received message from', sender); + console.log(JSON.stringify(message)); const sendResponseWithSender = (response: ActionPayload) => sendResponse({ ...response, sender: SENDER_BACKGROUND_SCRIPT }); diff --git a/holo-key-manager-extension/scripts/content.ts b/holo-key-manager-extension/scripts/content.ts index 94c8cac..edfbf89 100644 --- a/holo-key-manager-extension/scripts/content.ts +++ b/holo-key-manager-extension/scripts/content.ts @@ -7,10 +7,6 @@ const parseAndHandleMessage = async (event: MessageEvent) => { const parsedResult = MessageWithIdSchema.safeParse(event.data); if (!parsedResult.success || parsedResult.data.sender === SENDER_BACKGROUND_SCRIPT) return; try { - window.postMessage('Sending message to background script', '*'); - window.postMessage(JSON.stringify(chrome), '*'); - window.postMessage(JSON.stringify(chrome.runtime), '*'); - window.postMessage(JSON.stringify(chrome.runtime.sendMessage), '*'); const response = await sendMessage({ ...parsedResult.data, origin: event.origin }); const parsedMessageSchema = parseMessageSchema(response); window.postMessage(responseToMessage(parsedMessageSchema.data, parsedResult.data.id), '*'); diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index 67274ae..b6ac8b6 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -9,8 +9,21 @@ export default async function needsSetupTest(browser: Browser) { const page = await browser.newPage(); await page.goto('http://localhost:3007/tests/test.html'); - const targets = browser.targets(); - console.log(targets); + // Find the service worker target + const swTarget = await browser.waitForTarget((target) => target.type() === 'service_worker'); + + // Create a new page for the service worker + const swPage = await swTarget.createCDPSession(); + + // Enable console logging for the service worker + await swPage.send('Runtime.enable'); + + // Listen for console messages from the service worker + swPage.on('Runtime.consoleAPICalled', (event) => { + const { type, args } = event; + const formattedArgs = args.map((arg) => arg.value || arg.description).join(', '); + console.log(`Service Worker Console [${type}]: ${formattedArgs}`); + }); await page.evaluate(() => { window.addEventListener('message', (event) => { From ca5ef5d2b266ce10bf5978cbf7dcc72f3c168195 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 14:48:25 +0200 Subject: [PATCH 33/49] change cache --- .github/workflows/extension-PR.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/extension-PR.yaml b/.github/workflows/extension-PR.yaml index 5e39094..953c420 100644 --- a/.github/workflows/extension-PR.yaml +++ b/.github/workflows/extension-PR.yaml @@ -32,7 +32,7 @@ jobs: path: | holo-key-manager-extension/build holo-key-manager-js-client/lib - key: test-cache-1 + key: test-cache-2 - name: Run unit tests run: pnpm test From 28626ec1453795a5e0aaeb3918453ec929e59fd0 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 14:50:48 +0200 Subject: [PATCH 34/49] check logs --- holo-key-manager-extension/scripts/background.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/holo-key-manager-extension/scripts/background.ts b/holo-key-manager-extension/scripts/background.ts index 594f17b..7fa9d36 100644 --- a/holo-key-manager-extension/scripts/background.ts +++ b/holo-key-manager-extension/scripts/background.ts @@ -137,6 +137,7 @@ const processMessageWebApp = async ( sendResponseWithSender: SendResponseWithSender ) => { try { + console.log(JSON.stringify(parsedMessage)); if (!(await isSetupComplete())) { return updateOrCreateWindow(NEEDS_SETUP, sendResponseWithSender); } @@ -196,7 +197,6 @@ const processMessageExtension = async ( }; chrome.runtime.onMessage.addListener((message: Message, sender, sendResponse: SendResponse) => { - console.log(JSON.stringify(message)); const sendResponseWithSender = (response: ActionPayload) => sendResponse({ ...response, sender: SENDER_BACKGROUND_SCRIPT }); From d1d8da83a033b82f7535f71622635a1939e8526e Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 14:52:43 +0200 Subject: [PATCH 35/49] Test console --- holo-key-manager-extension/scripts/background.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/holo-key-manager-extension/scripts/background.ts b/holo-key-manager-extension/scripts/background.ts index 7fa9d36..7ac784a 100644 --- a/holo-key-manager-extension/scripts/background.ts +++ b/holo-key-manager-extension/scripts/background.ts @@ -137,8 +137,8 @@ const processMessageWebApp = async ( sendResponseWithSender: SendResponseWithSender ) => { try { - console.log(JSON.stringify(parsedMessage)); if (!(await isSetupComplete())) { + console.log(JSON.stringify(parsedMessage)); return updateOrCreateWindow(NEEDS_SETUP, sendResponseWithSender); } switch (parsedMessage.action) { From 905c55de3745833967ac8073161117c955da042a Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 14:57:10 +0200 Subject: [PATCH 36/49] Test console --- holo-key-manager-extension/scripts/background.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/holo-key-manager-extension/scripts/background.ts b/holo-key-manager-extension/scripts/background.ts index 7ac784a..fc53f95 100644 --- a/holo-key-manager-extension/scripts/background.ts +++ b/holo-key-manager-extension/scripts/background.ts @@ -62,6 +62,7 @@ const createOrUpdateWindow = ( windowProperties: WindowProperties, handleWindowUpdateOrCreate: () => Promise ) => { + console.log(2); const onWindowCreated = (newWindow: chrome.windows.Window | undefined) => { if (!newWindow) return; windowId = newWindow.id; @@ -71,6 +72,8 @@ const createOrUpdateWindow = ( handleWindowUpdateOrCreate(); }; + console.log(windowId); + if (windowId) { chrome.windows.remove(windowId, () => { windowId = undefined; @@ -138,7 +141,7 @@ const processMessageWebApp = async ( ) => { try { if (!(await isSetupComplete())) { - console.log(JSON.stringify(parsedMessage)); + console.log('1'); return updateOrCreateWindow(NEEDS_SETUP, sendResponseWithSender); } switch (parsedMessage.action) { From 3ab8b9b501d4f314b307c4f5bf71c2c63ed0d921 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 15:01:00 +0200 Subject: [PATCH 37/49] Test console --- holo-key-manager-extension/scripts/background.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/holo-key-manager-extension/scripts/background.ts b/holo-key-manager-extension/scripts/background.ts index fc53f95..51d1718 100644 --- a/holo-key-manager-extension/scripts/background.ts +++ b/holo-key-manager-extension/scripts/background.ts @@ -62,8 +62,9 @@ const createOrUpdateWindow = ( windowProperties: WindowProperties, handleWindowUpdateOrCreate: () => Promise ) => { - console.log(2); const onWindowCreated = (newWindow: chrome.windows.Window | undefined) => { + console.log(3); + console.log(newWindow); if (!newWindow) return; windowId = newWindow.id; chrome.windows.onRemoved.addListener((id) => { @@ -72,8 +73,6 @@ const createOrUpdateWindow = ( handleWindowUpdateOrCreate(); }; - console.log(windowId); - if (windowId) { chrome.windows.remove(windowId, () => { windowId = undefined; @@ -141,7 +140,6 @@ const processMessageWebApp = async ( ) => { try { if (!(await isSetupComplete())) { - console.log('1'); return updateOrCreateWindow(NEEDS_SETUP, sendResponseWithSender); } switch (parsedMessage.action) { From 4d975cb5a9fb90cba58597b286b5b6b8bb15074e Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 15:17:59 +0200 Subject: [PATCH 38/49] Test console --- holo-key-manager-extension/scripts/background.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/holo-key-manager-extension/scripts/background.ts b/holo-key-manager-extension/scripts/background.ts index 51d1718..c5425a9 100644 --- a/holo-key-manager-extension/scripts/background.ts +++ b/holo-key-manager-extension/scripts/background.ts @@ -64,7 +64,7 @@ const createOrUpdateWindow = ( ) => { const onWindowCreated = (newWindow: chrome.windows.Window | undefined) => { console.log(3); - console.log(newWindow); + console.log('newWindow', newWindow); if (!newWindow) return; windowId = newWindow.id; chrome.windows.onRemoved.addListener((id) => { @@ -73,6 +73,8 @@ const createOrUpdateWindow = ( handleWindowUpdateOrCreate(); }; + console.log('windowId', windowId); + if (windowId) { chrome.windows.remove(windowId, () => { windowId = undefined; From eef5fb0c65e58e161884867111fb3f6fd015f296 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 15:22:56 +0200 Subject: [PATCH 39/49] Test windowProperties --- holo-key-manager-extension/scripts/background.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/holo-key-manager-extension/scripts/background.ts b/holo-key-manager-extension/scripts/background.ts index c5425a9..9f56b7a 100644 --- a/holo-key-manager-extension/scripts/background.ts +++ b/holo-key-manager-extension/scripts/background.ts @@ -73,7 +73,7 @@ const createOrUpdateWindow = ( handleWindowUpdateOrCreate(); }; - console.log('windowId', windowId); + console.log(windowProperties); if (windowId) { chrome.windows.remove(windowId, () => { From 1b2d9257d5462e77aad10f9a63a49ef5732bd41d Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 15:25:09 +0200 Subject: [PATCH 40/49] Test windowProperties --- holo-key-manager-extension/scripts/background.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/holo-key-manager-extension/scripts/background.ts b/holo-key-manager-extension/scripts/background.ts index 9f56b7a..2e00898 100644 --- a/holo-key-manager-extension/scripts/background.ts +++ b/holo-key-manager-extension/scripts/background.ts @@ -73,7 +73,7 @@ const createOrUpdateWindow = ( handleWindowUpdateOrCreate(); }; - console.log(windowProperties); + console.log(JSON.stringify(windowProperties)); if (windowId) { chrome.windows.remove(windowId, () => { From 13cd4f7d921c8c261e0ccdc31d74e5e21aa580d6 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 15:25:47 +0200 Subject: [PATCH 41/49] error handling --- holo-key-manager-extension/scripts/background.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/holo-key-manager-extension/scripts/background.ts b/holo-key-manager-extension/scripts/background.ts index 2e00898..987c627 100644 --- a/holo-key-manager-extension/scripts/background.ts +++ b/holo-key-manager-extension/scripts/background.ts @@ -65,6 +65,10 @@ const createOrUpdateWindow = ( const onWindowCreated = (newWindow: chrome.windows.Window | undefined) => { console.log(3); console.log('newWindow', newWindow); + if (chrome.runtime.lastError) { + console.error('Window creation error:', chrome.runtime.lastError); + } + if (!newWindow) return; windowId = newWindow.id; chrome.windows.onRemoved.addListener((id) => { From eb87c33095c1240a380f680741d190c8988c7e5a Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 15:26:41 +0200 Subject: [PATCH 42/49] Test 3 --- tests/helpers.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/helpers.ts b/tests/helpers.ts index 1491e3b..03014f5 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -10,7 +10,12 @@ export const launchBrowserWithExtension = async (extensionPath: string): Promise return launch({ dumpio: true, headless: true, - args: [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`] + args: [ + `--disable-extensions-except=${extensionPath}`, + `--load-extension=${extensionPath}`, + '--no-sandbox', + '--disable-setuid-sandbox' + ] }); }; From 12232c10bb8c506b7eaf17119de13aae92310ce3 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 15:28:23 +0200 Subject: [PATCH 43/49] Test 4 --- holo-key-manager-extension/scripts/background.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/holo-key-manager-extension/scripts/background.ts b/holo-key-manager-extension/scripts/background.ts index 987c627..17d2b20 100644 --- a/holo-key-manager-extension/scripts/background.ts +++ b/holo-key-manager-extension/scripts/background.ts @@ -63,10 +63,8 @@ const createOrUpdateWindow = ( handleWindowUpdateOrCreate: () => Promise ) => { const onWindowCreated = (newWindow: chrome.windows.Window | undefined) => { - console.log(3); - console.log('newWindow', newWindow); if (chrome.runtime.lastError) { - console.error('Window creation error:', chrome.runtime.lastError); + console.error('Window creation error:', JSON.stringify(chrome.runtime.lastError)); } if (!newWindow) return; From 56614a399f7de3edee367731a99a158c8b06ffba Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 15:32:28 +0200 Subject: [PATCH 44/49] Test window size --- tests/helpers.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/helpers.ts b/tests/helpers.ts index 03014f5..ee4be26 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -13,8 +13,7 @@ export const launchBrowserWithExtension = async (extensionPath: string): Promise args: [ `--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`, - '--no-sandbox', - '--disable-setuid-sandbox' + '--window-size=1920,1080' ] }); }; From 63a1d7a783e02080a65ad5302093970f9750c882 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 15:35:33 +0200 Subject: [PATCH 45/49] Fix defaultViewport --- tests/helpers.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/helpers.ts b/tests/helpers.ts index ee4be26..08fb557 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -14,7 +14,11 @@ export const launchBrowserWithExtension = async (extensionPath: string): Promise `--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`, '--window-size=1920,1080' - ] + ], + defaultViewport: { + width: 1920, + height: 1080 + } }); }; From a8521890501f207d8bbb9bee6ae6bb8ab4613eaf Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 15:59:30 +0200 Subject: [PATCH 46/49] Test createWindowProperties --- holo-key-manager-extension/scripts/background.ts | 2 +- tests/helpers.ts | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/holo-key-manager-extension/scripts/background.ts b/holo-key-manager-extension/scripts/background.ts index 17d2b20..8f2344c 100644 --- a/holo-key-manager-extension/scripts/background.ts +++ b/holo-key-manager-extension/scripts/background.ts @@ -55,7 +55,7 @@ const createWindowProperties = (parsedMessage?: MessageWithId): WindowProperties height: 500, width: 375, top: 100, - left: 1100 + left: 0 }); const createOrUpdateWindow = ( diff --git a/tests/helpers.ts b/tests/helpers.ts index 08fb557..1491e3b 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -10,15 +10,7 @@ export const launchBrowserWithExtension = async (extensionPath: string): Promise return launch({ dumpio: true, headless: true, - args: [ - `--disable-extensions-except=${extensionPath}`, - `--load-extension=${extensionPath}`, - '--window-size=1920,1080' - ], - defaultViewport: { - width: 1920, - height: 1080 - } + args: [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`] }); }; From 74ed3372a653852b6907cc55ff86e86a22879898 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 16:18:11 +0200 Subject: [PATCH 47/49] Fix creating windows --- .github/workflows/extension-PR.yaml | 9 --- .../build-scripts/replaceForFirefox.cjs | 4 ++ .../scripts/background.ts | 56 +++++++++++++------ .../static/manifest.json | 2 +- tests/index.test.ts | 17 +++--- 5 files changed, 52 insertions(+), 36 deletions(-) diff --git a/.github/workflows/extension-PR.yaml b/.github/workflows/extension-PR.yaml index 953c420..86101e4 100644 --- a/.github/workflows/extension-PR.yaml +++ b/.github/workflows/extension-PR.yaml @@ -25,15 +25,6 @@ jobs: - name: Install dependencies run: pnpm install --no-frozen-lockfile - - name: Cache build - id: cache-build - uses: actions/cache@v4 - with: - path: | - holo-key-manager-extension/build - holo-key-manager-js-client/lib - key: test-cache-2 - - name: Run unit tests run: pnpm test working-directory: holo-key-manager-extension diff --git a/holo-key-manager-extension/build-scripts/replaceForFirefox.cjs b/holo-key-manager-extension/build-scripts/replaceForFirefox.cjs index 58e17fa..f7f2a95 100644 --- a/holo-key-manager-extension/build-scripts/replaceForFirefox.cjs +++ b/holo-key-manager-extension/build-scripts/replaceForFirefox.cjs @@ -16,8 +16,12 @@ const exitWithError = (message) => { const updateManifest = (data, geckoId) => { const manifest = JSON.parse(data); const { key, ...rest } = manifest; + const updatedPermissions = rest.permissions.filter( + (permission) => permission !== 'system.display' + ); return { ...rest, + permissions: updatedPermissions, background: { scripts: ['scripts/background.js'], type: 'module' diff --git a/holo-key-manager-extension/scripts/background.ts b/holo-key-manager-extension/scripts/background.ts index 8f2344c..09e0371 100644 --- a/holo-key-manager-extension/scripts/background.ts +++ b/holo-key-manager-extension/scripts/background.ts @@ -49,16 +49,40 @@ const handleError = (sendResponse: SendResponseWithSender) => { sendResponse({ action: GENERIC_ERROR }); }; -const createWindowProperties = (parsedMessage?: MessageWithId): WindowProperties => ({ - url: `webapp-extension/setup.html${parsedMessage ? `?${createQueryParams(parsedMessage)}` : ''}`, - type: 'popup', - height: 500, - width: 375, - top: 100, - left: 0 -}); +const createWindowProperties = async (parsedMessage?: MessageWithId): Promise => { + const width = 375; + const height = 500; + const defaultLeft = 1100; + const defaultTop = 100; -const createOrUpdateWindow = ( + const getDisplayInfo = async () => { + try { + const displays = await chrome.system.display.getInfo(); + return displays.find((d) => d.isPrimary) || displays[0]; + } catch (error) { + return null; + } + }; + + const calculatePosition = (display: chrome.system.display.DisplayInfo | null) => ({ + left: display ? display.workArea.width - width - 20 : defaultLeft, + top: display ? Math.min(defaultTop, display.workArea.height - height) : defaultTop + }); + + const primaryDisplay = await getDisplayInfo(); + const { left, top } = calculatePosition(primaryDisplay); + + return { + url: `webapp-extension/setup.html${parsedMessage ? `?${createQueryParams(parsedMessage)}` : ''}`, + type: 'popup', + width, + height, + top, + left + }; +}; + +const createOrUpdateWindow = async ( windowProperties: WindowProperties, handleWindowUpdateOrCreate: () => Promise ) => { @@ -75,8 +99,6 @@ const createOrUpdateWindow = ( handleWindowUpdateOrCreate(); }; - console.log(JSON.stringify(windowProperties)); - if (windowId) { chrome.windows.remove(windowId, () => { windowId = undefined; @@ -87,16 +109,16 @@ const createOrUpdateWindow = ( } }; -const updateOrCreateWindowCommon = ( +const updateOrCreateWindowCommon = async ( handleWindowUpdateOrCreate: () => Promise, parsedMessage?: MessageWithId -) => createOrUpdateWindow(createWindowProperties(parsedMessage), handleWindowUpdateOrCreate); +) => createOrUpdateWindow(await createWindowProperties(parsedMessage), handleWindowUpdateOrCreate); -const updateOrCreateWindow = ( +const updateOrCreateWindow = async ( successAction: typeof NEEDS_SETUP, sendResponse: SendResponseWithSender ) => - updateOrCreateWindowCommon(async () => { + await updateOrCreateWindowCommon(async () => { if (chrome.runtime.lastError) return handleError(sendResponse); try { sendResponse({ action: successAction }); @@ -123,11 +145,11 @@ const waitForFormSubmission = (id: string): Promise => chrome.runtime.onMessage.addListener(messageListener); }); -const createOrUpdateDataResponseWindow = ( +const createOrUpdateDataResponseWindow = async ( sendResponse: SendResponseWithSender, parsedMessage: MessageWithId ) => - updateOrCreateWindowCommon(async () => { + await updateOrCreateWindowCommon(async () => { if (chrome.runtime.lastError) return handleError(sendResponse); try { diff --git a/holo-key-manager-extension/static/manifest.json b/holo-key-manager-extension/static/manifest.json index 23a450b..559ab70 100644 --- a/holo-key-manager-extension/static/manifest.json +++ b/holo-key-manager-extension/static/manifest.json @@ -16,7 +16,7 @@ "service_worker": "scripts/background.js", "type": "module" }, - "permissions": ["activeTab", "storage", "tabs", "nativeMessaging"], + "permissions": ["activeTab", "storage", "tabs", "nativeMessaging", "system.display"], "content_scripts": [ { "matches": [""], diff --git a/tests/index.test.ts b/tests/index.test.ts index 411a6ca..6e8978b 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -5,11 +5,10 @@ import { resolve } from 'path'; import type { Browser } from 'puppeteer'; import { afterAll, beforeAll, describe, it } from 'vitest'; -// import clientInteractionTest from './clientInteraction'; +import clientInteractionTest from './clientInteraction'; import { launchBrowserWithExtension, startServer } from './helpers'; import needsSetupTest from './needsSetup'; -// import needsSetupTest from './needsSetup'; -// import preventSignatureFromOtherOrigin from './preventSignatureFromOtherOrigin'; +import preventSignatureFromOtherOrigin from './preventSignatureFromOtherOrigin'; import setupFlowTest from './setupFlow'; dotenv.config(); @@ -48,11 +47,11 @@ describe('End-to-End Tests for Extension and Client', () => { await setupFlowTest(browser, EXTENSION_ID); }); - // it('should allow the client to interact with the extension after setup', async () => { - // await clientInteractionTest(browser); - // }); + it('should allow the client to interact with the extension after setup', async () => { + await clientInteractionTest(browser); + }); - // it('should prevent the malicious page from signing messages', async () => { - // await preventSignatureFromOtherOrigin(browser); - // }); + it('should prevent the malicious page from signing messages', async () => { + await preventSignatureFromOtherOrigin(browser); + }); }); From bfa9ad60aa0c3700e42f17c387708743bea58e48 Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 16:26:40 +0200 Subject: [PATCH 48/49] Fix after debugging --- .github/workflows/extension-PR.yaml | 2 -- .github/workflows/extension.yaml | 4 +-- .husky/pre-commit | 2 -- package.json | 3 +-- pnpm-lock.yaml | 42 ++++++++++++++--------------- tests/helpers.ts | 11 +++----- tests/index.test.ts | 2 +- tests/needsSetup.ts | 33 ----------------------- tests/setupFlow.ts | 10 ------- 9 files changed, 28 insertions(+), 81 deletions(-) diff --git a/.github/workflows/extension-PR.yaml b/.github/workflows/extension-PR.yaml index 86101e4..0702b2c 100644 --- a/.github/workflows/extension-PR.yaml +++ b/.github/workflows/extension-PR.yaml @@ -30,12 +30,10 @@ jobs: working-directory: holo-key-manager-extension - name: Build extension - if: steps.cache-build.outputs.cache-hit != 'true' run: pnpm build working-directory: holo-key-manager-extension - name: Build client - if: steps.cache-build.outputs.cache-hit != 'true' run: pnpm build working-directory: holo-key-manager-js-client diff --git a/.github/workflows/extension.yaml b/.github/workflows/extension.yaml index aa1389c..dda0053 100644 --- a/.github/workflows/extension.yaml +++ b/.github/workflows/extension.yaml @@ -71,8 +71,8 @@ jobs: run: pnpm build working-directory: holo-key-manager-extension - - name: Build and pack client - run: pnpm buildPack + - name: Build client + run: pnpm build working-directory: holo-key-manager-js-client - name: Run e2e tests diff --git a/.husky/pre-commit b/.husky/pre-commit index f654052..2312dc5 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,3 +1 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" npx lint-staged diff --git a/package.json b/package.json index c60b117..54fb6f0 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,6 @@ "prepare": "husky install", "test": "concurrently \"pnpm e2e-tests\" \"cd holo-key-manager-extension && pnpm test\" \"cd holo-key-manager-js-client && pnpm test\"", "e2e-tests": "vitest run" - }, "devDependencies": { "@rollup/plugin-node-resolve": "^15.2.3", @@ -35,7 +34,7 @@ "eslint-plugin-svelte": "^2.42.0", "express": "^4.19.2", "globals": "^15.8.0", - "husky": "^9.1.0", + "husky": "^9.1.1", "jszip": "^3.10.1", "lint-staged": "^15.2.5", "prettier": "^3.3.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9633ed2..eb1af0e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -52,8 +52,8 @@ importers: specifier: ^15.8.0 version: 15.8.0 husky: - specifier: ^9.1.0 - version: 9.1.0 + specifier: ^9.1.1 + version: 9.1.1 jszip: specifier: ^3.10.1 version: 3.10.1 @@ -101,7 +101,7 @@ importers: version: 3.0.0-beta2 '@tanstack/svelte-query': specifier: ^5.46.1 - version: 5.51.5(svelte@4.2.18) + version: 5.51.9(svelte@4.2.18) blakejs: specifier: ^1.2.1 version: 1.2.1 @@ -650,11 +650,11 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.0 - '@tanstack/query-core@5.51.5': - resolution: {integrity: sha512-qovOto6hFet2zA4Pf3cDO+qkOqskO6xP39PlKnr6YKPtjRsePWyZnTaMf59+VnlOLY8gpku1I4WPC4dqBXo4FQ==} + '@tanstack/query-core@5.51.9': + resolution: {integrity: sha512-HsAwaY5J19MD18ykZDS3aVVh+bAt0i7m6uQlFC2b77DLV9djo+xEN7MWQAQQTR8IM+7r/zbozTQ7P0xr0bHuew==} - '@tanstack/svelte-query@5.51.5': - resolution: {integrity: sha512-6POqaWbhmkyFosZfA9lYJC5q+pehWQ6Ykkxq+s5wgrHdSAMw/q9t124Z92WcK7YTia5GXMJ0OTNsprh64ZFw8g==} + '@tanstack/svelte-query@5.51.9': + resolution: {integrity: sha512-u9U/Lo/5TrQ1bzBP5DPKfACNLAiY0BySeRaKC5Xn45+5k9aD3BZVCOIsTAprkByBklsshWkueXE0QQiCo7LPeQ==} peerDependencies: svelte: ^3.54.0 || ^4.0.0 || ^5.0.0-next.0 @@ -1661,8 +1661,8 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} - husky@9.1.0: - resolution: {integrity: sha512-8XCjbomYTGdNF2h50dio3T3zghmZ9f/ZNzr99YwSkvDdhEjJGs5qzy8tbFx+SG8yCx2wn9nMVfZxVrr/yT8gNQ==} + husky@9.1.1: + resolution: {integrity: sha512-fCqlqLXcBnXa/TJXmT93/A36tJsjdJkibQ1MuIiFyCCYUlpYpIaj2mv1w+3KR6Rzu1IC3slFTje5f6DUp2A2rg==} engines: {node: '>=18'} hasBin: true @@ -1843,11 +1843,11 @@ packages: libsodium-wrappers-sumo@0.7.13: resolution: {integrity: sha512-lz4YdplzDRh6AhnLGF2Dj2IUj94xRN6Bh8T0HLNwzYGwPehQJX6c7iYVrFUPZ3QqxE0bqC+K0IIqqZJYWumwSQ==} - libsodium-wrappers@0.7.13: - resolution: {integrity: sha512-kasvDsEi/r1fMzKouIDv7B8I6vNmknXwGiYodErGuESoFTohGSKZplFtVxZqHaoQ217AynyIFgnOVRitpHs0Qw==} + libsodium-wrappers@0.7.14: + resolution: {integrity: sha512-300TtsePizhJZ7HjLmWr6hLHAgJUxIGhapSw+EwfCtDuWaEmEdGXSQv6j6qFw0bs9l4vS2NH9BtOHfXAq6h5kQ==} - libsodium@0.7.13: - resolution: {integrity: sha512-mK8ju0fnrKXXfleL53vtp9xiPq5hKM0zbDQtcxQIsSmxNgSxqCj6R7Hl9PkrNe2j29T4yoDaF7DJLK9/i5iWUw==} + libsodium@0.7.14: + resolution: {integrity: sha512-/pOd7eO6oZrfORquRTC4284OUJFcMi8F3Vnc9xtRBT0teLfOUxWIItaBFF3odYjZ7nlJNwnLdUVEUFHxVyX/Sw==} lie@3.3.0: resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} @@ -3249,7 +3249,7 @@ snapshots: emittery: 1.0.3 isomorphic-ws: 5.0.0(ws@8.18.0) js-base64: 3.7.7 - libsodium-wrappers: 0.7.13 + libsodium-wrappers: 0.7.14 lodash-es: 4.17.21 ws: 8.18.0 transitivePeerDependencies: @@ -3490,11 +3490,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/query-core@5.51.5': {} + '@tanstack/query-core@5.51.9': {} - '@tanstack/svelte-query@5.51.5(svelte@4.2.18)': + '@tanstack/svelte-query@5.51.9(svelte@4.2.18)': dependencies: - '@tanstack/query-core': 5.51.5 + '@tanstack/query-core': 5.51.9 svelte: 4.2.18 '@tootallnate/quickjs-emscripten@0.23.0': {} @@ -4637,7 +4637,7 @@ snapshots: human-signals@5.0.0: {} - husky@9.1.0: {} + husky@9.1.1: {} iconv-lite@0.4.24: dependencies: @@ -4794,11 +4794,11 @@ snapshots: dependencies: libsodium-sumo: 0.7.13 - libsodium-wrappers@0.7.13: + libsodium-wrappers@0.7.14: dependencies: - libsodium: 0.7.13 + libsodium: 0.7.14 - libsodium@0.7.13: {} + libsodium@0.7.14: {} lie@3.3.0: dependencies: diff --git a/tests/helpers.ts b/tests/helpers.ts index 1491e3b..f0ce401 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -8,7 +8,6 @@ import { vi } from 'vitest'; export const launchBrowserWithExtension = async (extensionPath: string): Promise => { return launch({ - dumpio: true, headless: true, args: [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`] }); @@ -63,13 +62,9 @@ export const findButtonExtensionByText = (context: Page) => export const findTextBySelector = (context: Page) => findElementByText(context, ''); export const startServer = (port: number = 3007): Server => { - try { - const app = express(); - app.use(express.static(resolve('./holo-key-manager-js-client'))); - return app.listen(port); - } catch (error) { - throw new Error(`Failed to start server: ${error}`); - } + const app = express(); + app.use(express.static(resolve('./holo-key-manager-js-client'))); + return app.listen(port); }; export const waitForNewPage = (browser: Browser): Promise => diff --git a/tests/index.test.ts b/tests/index.test.ts index 6e8978b..778163a 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -13,7 +13,7 @@ import setupFlowTest from './setupFlow'; dotenv.config(); -const EXTENSION_ID = process.env.CHROME_ID || 'eggfhkdnfdhdpmkfpihjjbnncgmhihce'; +const EXTENSION_ID = process.env.CHROME_ID; const downloadPath = resolve('./downloads'); diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index b6ac8b6..b45b214 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -9,39 +9,6 @@ export default async function needsSetupTest(browser: Browser) { const page = await browser.newPage(); await page.goto('http://localhost:3007/tests/test.html'); - // Find the service worker target - const swTarget = await browser.waitForTarget((target) => target.type() === 'service_worker'); - - // Create a new page for the service worker - const swPage = await swTarget.createCDPSession(); - - // Enable console logging for the service worker - await swPage.send('Runtime.enable'); - - // Listen for console messages from the service worker - swPage.on('Runtime.consoleAPICalled', (event) => { - const { type, args } = event; - const formattedArgs = args.map((arg) => arg.value || arg.description).join(', '); - console.log(`Service Worker Console [${type}]: ${formattedArgs}`); - }); - - await page.evaluate(() => { - window.addEventListener('message', (event) => { - console.log(event.data); - }); - }); - - page.on('console', async (message) => { - const type = message.type(); - const text = await message.text(); - const args = await Promise.all(message.args().map((arg) => arg.jsonValue())); - - const formattedArgs = args.map((arg) => JSON.stringify(arg)).join(', '); - console.log( - `Console message [${type}]: ${text}${formattedArgs ? ` | Args: ${formattedArgs}` : ''}` - ); - }); - const findTextOnPage = findTextBySelector(page); const signUpButton = await findTextOnPage('Sign Up'); diff --git a/tests/setupFlow.ts b/tests/setupFlow.ts index f5d5ce0..7d633bf 100644 --- a/tests/setupFlow.ts +++ b/tests/setupFlow.ts @@ -21,16 +21,6 @@ export default async function setupFlowTest(browser: Browser, EXTENSION_ID: stri const page = await openExtensionPage(browser, EXTENSION_ID); - const targets = browser.targets(); - console.log(targets); - const serviceWorkerTarget = targets.find((target) => target.type() === 'service_worker'); - - if (serviceWorkerTarget) { - console.log('Service worker from this extension is working'); - } else { - console.log('Service worker from this extension is not detected'); - } - const setupButton = await findButtonExtensionByText(page)('Setup'); const setupPageContent = await findTextBySelector(page)('Setup Required'); From 8a1717466efab994fa81b293a94193ef7990953a Mon Sep 17 00:00:00 2001 From: Dawid Urbas Date: Thu, 18 Jul 2024 16:31:14 +0200 Subject: [PATCH 49/49] Fix unnecessary code --- holo-key-manager-js-client/tests/test.html | 2 -- tests/needsSetup.ts | 2 -- 2 files changed, 4 deletions(-) diff --git a/holo-key-manager-js-client/tests/test.html b/holo-key-manager-js-client/tests/test.html index 34f5268..9606510 100644 --- a/holo-key-manager-js-client/tests/test.html +++ b/holo-key-manager-js-client/tests/test.html @@ -21,11 +21,9 @@ document.getElementById(buttonId).addEventListener('click', async () => { const resultElement = document.getElementById(`${buttonId}Result`); try { - console.log('Action:', action); const result = await action(); resultElement.textContent = `${buttonId} successful: ${JSON.stringify(result)}`; } catch (error) { - console.log('Error:', error); resultElement.textContent = `Error: ${error.message}`; } }); diff --git a/tests/needsSetup.ts b/tests/needsSetup.ts index b45b214..a22bf8c 100644 --- a/tests/needsSetup.ts +++ b/tests/needsSetup.ts @@ -3,8 +3,6 @@ import { expect } from 'vitest'; import { findTextBySelector } from './helpers'; -// import { findTextBySelector } from './helpers'; - export default async function needsSetupTest(browser: Browser) { const page = await browser.newPage(); await page.goto('http://localhost:3007/tests/test.html');