diff --git a/background/package.json b/background/package.json index ff11e10..e2edf4e 100644 --- a/background/package.json +++ b/background/package.json @@ -7,7 +7,7 @@ "serve": "vite preview --port 8002", "build": "vite build --base /background --outDir ../build/background", "fmt": "pnpm dlx @biomejs/biome format --write ./src", - "test": "jest --coverage --detectOpenHandles" + "test": "vitest" }, "dependencies": { "@noble/hashes": "^1.4.0", @@ -28,13 +28,12 @@ "@types/chrome": "^0.0.266", "@typescript-eslint/eslint-plugin": "^7.2.0", "@vue/test-utils": "^1.3.0", - "axios-mock-adapter": "^1.20.0", "eslint": "^7.32.0", "eslint-plugin-vue": "^8.7.1", - "jest": "^27.4.5", - "jest-serializer-vue": "^2.0.2", + "fast-check": "^3.19.0", "typescript": "^5.4.5", "vite": "^5.2.8", + "vitest": "^1.6.0", "vue-jest": "^3.0.7" }, "eslintConfig": { diff --git a/background/src/api/graphql.ts b/background/src/api/graphql.ts index 6bc7a36..4cd4af1 100644 --- a/background/src/api/graphql.ts +++ b/background/src/api/graphql.ts @@ -1,5 +1,5 @@ import axios from "axios"; -import type Storage from "@/storage/storage"; +import type LocalStorage from "@/storage/local"; import { CURRENT_NETWORK, NETWORKS, @@ -29,7 +29,7 @@ async function getLastBlockIndex(endpoint: string) { return data["data"]["chainQuery"]["blockQuery"]["blocks"][0]["index"]; } -async function getEndpoints(storage: Storage): Promise { +async function getEndpoints(storage: LocalStorage): Promise { const currentNetworkId = await storage.get(CURRENT_NETWORK); const networks = await storage.get(NETWORKS); const network = networks.find((n) => n.id === currentNetworkId); @@ -59,7 +59,7 @@ async function getEndpoints(storage: Storage): Promise { } export default class Graphql { - private readonly storage: Storage; + private readonly storage: LocalStorage; private readonly endpoints: string[]; private readonly canCall: string[]; @@ -80,7 +80,7 @@ export default class Graphql { return this.canCall.indexOf(method) >= 0; } - static async createInstance(storage: Storage) { + static async createInstance(storage: LocalStorage) { const endpoints = await getEndpoints(storage); return new Graphql(storage, endpoints); } diff --git a/background/src/controllers/confirmation.ts b/background/src/controllers/confirmation.ts index 7e8a350..504418c 100644 --- a/background/src/controllers/confirmation.ts +++ b/background/src/controllers/confirmation.ts @@ -1,7 +1,7 @@ -import Storage from "@/storage/storage"; import { APPROVAL_REQUESTS } from "@/constants/constants"; import { nanoid } from "nanoid"; import { PopupController } from "./popup"; +import { IStorage } from "@/storage"; interface Request { id: string; @@ -18,7 +18,7 @@ const pendingApprovals: Map = new Map(); export class ConfirmationController { constructor( - private readonly storage: Storage, + private readonly storage: IStorage, private readonly popupController: PopupController, ) {} diff --git a/background/src/controllers/network.ts b/background/src/controllers/network.ts index d707b64..069b17e 100644 --- a/background/src/controllers/network.ts +++ b/background/src/controllers/network.ts @@ -1,4 +1,4 @@ -import Storage from "@/storage/storage"; +import { IStorage } from "@/storage/index.js"; import { CURRENT_NETWORK, NETWORKS, @@ -9,7 +9,7 @@ import { Emitter } from "@/event"; export class NetworkController { constructor( - private readonly storage: Storage, + private readonly storage: IStorage, private readonly emitter: Emitter, ) {} diff --git a/background/src/main.ts b/background/src/main.ts index acf695c..0e84409 100644 --- a/background/src/main.ts +++ b/background/src/main.ts @@ -1,5 +1,5 @@ import Graphql from "@/api/graphql"; -import Storage from "@/storage/storage"; +import { Storage } from "@/storage/index.js"; import Wallet from "@/wallet/wallet"; import { Buffer } from "buffer"; import { @@ -119,7 +119,8 @@ window.Buffer = Buffer; } if (req.action == "wallet") { - Wallet.createInstance(passphrase, emitter).then((wallet) => { + const storage = new Storage(passphrase); + Wallet.createInstance(storage, passphrase, emitter).then((wallet) => { if (wallet[req.method] && wallet.canCallExternal(req.method)) { wallet[req.method] .call(wallet, ...req.params) @@ -176,46 +177,50 @@ window.Buffer = Buffer; port.onMessage.addListener(function (req) { console.log(port.name, req); if (req.action == "wallet") { - Wallet.createInstance(() => passphrase, emitter, req.origin).then( - (wallet) => { - wallet.isConnected().then((connected) => { - if ( - !connected && - req.method !== "connect" && - req.method !== "isConnected" - ) { - port.postMessage({ - error: `${req.origin} is not connected. Call 'window.chronoWallet.connect' first.`, - messageId: req.messageId, - }); - } + const storage = new Storage(() => passphrase); + Wallet.createInstance( + storage, + () => passphrase, + emitter, + req.origin, + ).then((wallet) => { + wallet.isConnected().then((connected) => { + if ( + !connected && + req.method !== "connect" && + req.method !== "isConnected" + ) { + port.postMessage({ + error: `${req.origin} is not connected. Call 'window.chronoWallet.connect' first.`, + messageId: req.messageId, + }); + } - if (wallet[req.method] && wallet.canCallExternal(req.method)) { - wallet[req.method] - .call(wallet, ...req.params) - .then((x) => { - console.log(x); - port.postMessage({ - result: x, - messageId: req.messageId, - }); - }) - .catch((e) => { - console.error(e); - port.postMessage({ - error: `${req.method} is rejected`, - messageId: req.messageId, - }); + if (wallet[req.method] && wallet.canCallExternal(req.method)) { + wallet[req.method] + .call(wallet, ...req.params) + .then((x) => { + console.log(x); + port.postMessage({ + result: x, + messageId: req.messageId, + }); + }) + .catch((e) => { + console.error(e); + port.postMessage({ + error: `${req.method} is rejected`, + messageId: req.messageId, }); - } else { - port.postMessage({ - error: "Unknown Method", - messageId: req.messageId, }); - } - }); - }, - ); + } else { + port.postMessage({ + error: "Unknown Method", + messageId: req.messageId, + }); + } + }); + }); } if (req.action == "network") { diff --git a/background/src/storage/backend/common.ts b/background/src/storage/backend/common.ts new file mode 100644 index 0000000..59a50ba --- /dev/null +++ b/background/src/storage/backend/common.ts @@ -0,0 +1,4 @@ +export interface IStorageBackend { + get(key: string): Promise; + set(key: string, value: T): Promise; +} diff --git a/background/src/storage/backend/index.ts b/background/src/storage/backend/index.ts new file mode 100644 index 0000000..42096ac --- /dev/null +++ b/background/src/storage/backend/index.ts @@ -0,0 +1,2 @@ +export { IStorageBackend } from "./common.js"; +export { LocalStorageBackend } from "./local-storage.js"; diff --git a/background/src/storage/backend/local-storage.ts b/background/src/storage/backend/local-storage.ts new file mode 100644 index 0000000..453ab45 --- /dev/null +++ b/background/src/storage/backend/local-storage.ts @@ -0,0 +1,15 @@ +import { IStorageBackend } from "./common.js"; + +export class LocalStorageBackend implements IStorageBackend { + set(name: string, value: T): Promise { + return chrome.storage.local.set({ [name]: value }); + } + + get(name: string): Promise { + return new Promise((resolve) => { + chrome.storage.local.get([name], (res) => { + resolve((res && res[name]) || null); + }); + }); + } +} diff --git a/background/src/storage/common.ts b/background/src/storage/common.ts new file mode 100644 index 0000000..55d0b63 --- /dev/null +++ b/background/src/storage/common.ts @@ -0,0 +1,10 @@ +export interface IStorage { + canCallExternal(method: string): boolean; + secureSet(name: string, value: T): Promise; + secureGet(name: string): Promise; + set(name: string, value: T): Promise; + get(name: string): Promise; + remove(name: string): Promise; + has(name: string): Promise; + clearAll(): Promise; +} diff --git a/background/src/storage/index.ts b/background/src/storage/index.ts new file mode 100644 index 0000000..80ff2ce --- /dev/null +++ b/background/src/storage/index.ts @@ -0,0 +1,3 @@ +export { Storage } from "./storage.js"; + +export { IStorage } from "./common.js"; diff --git a/background/src/storage/storage.ts b/background/src/storage/storage.ts index 78a4b94..9900d43 100644 --- a/background/src/storage/storage.ts +++ b/background/src/storage/storage.ts @@ -1,11 +1,14 @@ import aes256 from "@/utils/aes256"; import { Lazyable, resolve } from "@/utils/lazy"; +import { IStorage } from "./common.js"; +import { IStorageBackend, LocalStorageBackend } from "./backend/index.js"; -class Storage { +export class Storage implements IStorage { private readonly passphrase: Lazyable; private readonly canCall: string[]; + private readonly backend: IStorageBackend; - constructor(passphrase: Lazyable) { + constructor(passphrase: Lazyable, backend?: IStorageBackend) { this.passphrase = passphrase; this.canCall = [ "set", @@ -15,20 +18,17 @@ class Storage { "secureSet", "clearAll", ] as const; + this.backend = backend || new LocalStorageBackend(); } canCallExternal(method: string): boolean { return this.canCall.indexOf(method) >= 0; } - async rawSet(name: string, value: T): Promise { - await chrome.storage.local.set({ [name]: value }); + private rawSet(name: string, value: T): Promise { + return this.backend.set(name, value); } - rawGet(name: string): Promise { - return new Promise((resolve) => { - chrome.storage.local.get([name], (res) => { - resolve((res && res[name]) || null); - }); - }); + private rawGet(name: string): Promise { + return this.backend.get(name); } /* @@ -85,4 +85,3 @@ class Storage { await chrome.storage.local.clear(); } } -export default Storage; diff --git a/background/src/utils/aes256.ts b/background/src/utils/aes256.ts index ef31fdb..b7e3790 100644 --- a/background/src/utils/aes256.ts +++ b/background/src/utils/aes256.ts @@ -3,15 +3,15 @@ import { keccak_256 } from "@noble/hashes/sha3"; const IV_LENGTH = 16; export default { encrypt: async (text: string, passphrase: string): Promise => { - const key = await window.crypto.subtle.importKey( + const key = await crypto.subtle.importKey( "raw", Buffer.from(keccak_256(passphrase)), { name: "AES-CBC" }, true, ["encrypt", "decrypt"], ); - const iv = window.crypto.getRandomValues(new Uint8Array(IV_LENGTH)); - const encrypted = await window.crypto.subtle.encrypt( + const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH)); + const encrypted = await crypto.subtle.encrypt( { name: "AES-CBC", iv, @@ -31,14 +31,14 @@ export default { const textParts = text.split(":"); const iv = Buffer.from(textParts.shift(), "hex"); const encryptedText = Buffer.from(textParts.join(":"), "hex"); - const key = await window.crypto.subtle.importKey( + const key = await crypto.subtle.importKey( "raw", Buffer.from(keccak_256(passphrase)), { name: "AES-CBC" }, true, ["encrypt", "decrypt"], ); - const decrypted = await window.crypto.subtle.decrypt( + const decrypted = await crypto.subtle.decrypt( { name: "AES-CBC", iv, diff --git a/background/src/wallet/wallet.ts b/background/src/wallet/wallet.ts index ad813ce..ca91ef2 100644 --- a/background/src/wallet/wallet.ts +++ b/background/src/wallet/wallet.ts @@ -1,5 +1,5 @@ import Graphql from "@/api/graphql"; -import Storage from "@/storage/storage"; +import { IStorage } from "@/storage/index.js"; import { ENCRYPTED_WALLET, TXS, @@ -50,7 +50,7 @@ interface SavedTransactionHistory { } export default class Wallet { - private readonly storage: Storage; + private readonly storage: IStorage; private readonly api: Graphql; private readonly popup: PopupController; private readonly networkController: NetworkController; @@ -69,7 +69,7 @@ export default class Wallet { constructor( passphrase: Lazyable, origin: string | undefined, - storage: Storage, + storage: IStorage, api: Graphql, popupController: PopupController, networkController: NetworkController, @@ -103,12 +103,12 @@ export default class Wallet { } static async createInstance( + storage: IStorage, passphrase: Lazyable, emitter: Emitter, origin?: string | undefined, ) { const popup = new PopupController(); - const storage = new Storage(passphrase); const api = await Graphql.createInstance(storage); const networkController = new NetworkController(storage, emitter); const approvalRequestController = new ConfirmationController( diff --git a/background/test/api/graphql.test.js b/background/test/api/graphql.test.js deleted file mode 100644 index 2e1755a..0000000 --- a/background/test/api/graphql.test.js +++ /dev/null @@ -1,38 +0,0 @@ -import Graphql from "@/api/graphql" -import Mock from "../mock" -Mock.mockGraphql() - -describe("graphql.js", () => { - let api - beforeAll(() => { - api = new Graphql() - }) - - test('Update Endpoints', async () => { - expect(api.endpoints.length).toBe(1) - Mock.graphql({ - endpoint: 'https://mercury2.9cscan.com/graphql/', - name:"getLastBlockIndex", - data: {"data": {"chainQuery": {"blockQuery": {"blocks": [{"index": 2972520}]}}}}, - once: true - }) - await api.updateNetwork() - expect(api.endpoints.length).toBe(2) - await api.updateNetwork() - expect(api.endpoints.length).toBe(1) - - await expect(api.updateNetwork('testnet')).rejects.toEqual('Unknown Network testnet') - }) - - test('Checking can call external', () => { - expect(api.canCallExternal('updateEndpoints')).toBeFalsy() - expect(api.canCallExternal('unsignedTx')).toBeFalsy() - expect(api.canCallExternal('attachSignature')).toBeFalsy() - expect(api.canCallExternal('stageTx')).toBeFalsy() - }) - - test('call test', () => { - expect(api.getBalance('address')).not.toBeNull() - expect(api.getActivationStatus('address')).not.toBeNull() - }) -}) \ No newline at end of file diff --git a/background/test/mock.js b/background/test/mock.js deleted file mode 100644 index 56efaf1..0000000 --- a/background/test/mock.js +++ /dev/null @@ -1,77 +0,0 @@ -import axios from "axios"; - -const MockAdapter = require("axios-mock-adapter") -const axiosMock = new MockAdapter(axios) - -export default { - graphql({endpoint = /.*/g, name='', data={}, once=false, responseCode=200}) { - let onPost = axiosMock.onPost(endpoint, { - asymmetricMatch: function (actual) { - return actual['query'] && actual['query'].indexOf(name) >= 0; - }, - }) - if (once) { - onPost.replyOnce(responseCode, data); - } else { - onPost.reply(responseCode, data); - } - }, - mockGraphql() { - this.graphql({ - endpoint: 'https://mars2.9cscan.com/graphql/', - name:"getLastBlockIndex", - data: {"data": {"chainQuery": {"blockQuery": {"blocks": [{"index": 2972520}]}}}} - }) - - this.graphql({ - name:"getBalance", - data: {"data": {"goldBalance": 100}} - }) - this.graphql({ - name:"getActivationStatus", - data: {"data": {"activationStatus": {"addressActivated": true}}} - }) - - this.graphql({ - name:"unsignedTx", - data: {"data": {transaction:{createUnsignedTx:"unsignedTx"}}} - }) - this.graphql({ - name:"attachSignature", - data: {"data": {transaction: {attachSignature: "tx"}}} - }) - this.graphql({ - name:"stageTx", - data: {data:{stageTxV2:"txId"}} - }) - - - }, - mockStorage() { - let data = {} - global.chrome = { - storage: { - local: { - set: (obj) => { - for (let key of Object.keys(obj)) { - data[key] = obj[key] - } - }, - get: (names, callback) => { - let result = {} - for (let name of names) { - result[name] = data[name] - } - callback(result) - }, - remove: (key) => { - delete data[key] - }, - clear: () => { - data = {} - } - } - } - } - } -} \ No newline at end of file diff --git a/background/test/storage/backend/memory.ts b/background/test/storage/backend/memory.ts new file mode 100644 index 0000000..04b4718 --- /dev/null +++ b/background/test/storage/backend/memory.ts @@ -0,0 +1,17 @@ +import { IStorageBackend } from "@/storage/backend/index.js"; + +export class InMemoryStorageBackend implements IStorageBackend { + private readonly map: Map = new Map(); + + constructor() { + this.map = new Map(); + } + + get(key: string): Promise { + return this.map.get(key); + } + + async set(key: string, value: T): Promise { + this.map.set(key, value); + } +} diff --git a/background/test/storage/storage.test.js b/background/test/storage/storage.test.js deleted file mode 100644 index ab6892b..0000000 --- a/background/test/storage/storage.test.js +++ /dev/null @@ -1,75 +0,0 @@ -import Storage from "@/storage/storage" -import Mock from "../mock" -const passphrase = 'Storage Passphrase' - -Mock.mockStorage() - -describe("storage.js", () => { - let storage - let key, numValue, strValue, objValue, arrValue - beforeAll(() => { - storage = new Storage(passphrase) - }) - beforeEach(() => { - key = 'key' + Math.random() - numValue = Math.random() - strValue = Math.random().toString() - objValue = {n: Math.random(), s: Math.random().toString()} - arrValue = [Math.random(), Math.random()] - }) - - test('Basic behavior test of set, get', async () => { - storage.clearAll() - - expect(await storage.has(key)).toBeFalsy() - storage.set(key, numValue) - expect(await storage.has(key)).toBeTruthy() - expect(await storage.rawGet(key)).not.toBe(numValue) - expect(await storage.get(key)).toBe(numValue) - - storage.set(key, strValue) - expect(await storage.rawGet(key)).not.toBe(strValue) - expect(await storage.get(key)).toBe(strValue) - - storage.set(key, objValue) - expect(JSON.stringify(await storage.rawGet(key))).not.toBe(JSON.stringify(objValue)) - expect(JSON.stringify(await storage.get(key))).toBe(JSON.stringify(objValue)) - - storage.set(key, arrValue) - expect(JSON.stringify(await storage.rawGet(key))).not.toBe(JSON.stringify(arrValue)) - expect(JSON.stringify(await storage.get(key))).toBe(JSON.stringify(arrValue)) - await expect(storage.secureGet(key)).rejects.toEqual('SecureGet has accessed to not secured data') - - expect(await storage.get(key + 'INVALID')).toBe(null) - }) - - - test('Basic behavior test of secureSet, secureGet', async () => { - storage.clearAll() - - expect(storage.canCallExternal('secureSet')).toBeTruthy() - expect(storage.canCallExternal('secureGet')).toBeFalsy() - - expect(await storage.has(key)).toBeFalsy() - storage.secureSet(key, numValue) - expect(await storage.has(key)).toBeTruthy() - expect(await storage.secureGet(key)).toBe(numValue) - await expect(storage.get(key)).rejects.toEqual('Can not access secure data') - storage.remove(key) - expect(await storage.has(key)).toBeFalsy() - - storage.secureSet(key, strValue) - expect(await storage.secureGet(key)).toBe(strValue) - await expect(storage.get(key)).rejects.toEqual('Can not access secure data') - - storage.secureSet(key, objValue) - expect(JSON.stringify(await storage.secureGet(key))).toBe(JSON.stringify(objValue)) - await expect(storage.get(key)).rejects.toEqual('Can not access secure data') - - storage.secureSet(key, arrValue) - expect(JSON.stringify(await storage.secureGet(key))).toBe(JSON.stringify(arrValue)) - await expect(storage.get(key)).rejects.toEqual('Can not access secure data') - - expect(await storage.secureGet(key + 'INVALID')).toBe(null) - }) -}) \ No newline at end of file diff --git a/background/test/storage/storage.test.ts b/background/test/storage/storage.test.ts new file mode 100644 index 0000000..87b788a --- /dev/null +++ b/background/test/storage/storage.test.ts @@ -0,0 +1,83 @@ +import { Storage } from "@/storage/index.js" +import { InMemoryStorageBackend } from "./backend/memory.js" +import { describe, expect, beforeEach, test } from "vitest"; +import { IStorageBackend } from "@/storage/backend/common.js"; +import fc from "fast-check"; +import aes256 from "@/utils/aes256.js"; + +// TODO: Check lazy passpharse. +const passphrase = 'Storage Passphrase' + +describe("Storage", () => { + let backend!: IStorageBackend; + let storage!: Storage; + + beforeEach(() => { + backend = new InMemoryStorageBackend(); + storage = new Storage(passphrase, backend); + }); + + describe('secureGet', () => { + test('should fail if the data is not secured', async () => { + fc.assert(fc.asyncProperty(fc.string(), fc.string(), async (key, value) => { + const v = await aes256.encrypt(JSON.stringify(value), passphrase); + await backend.set(`${key}-no-secure`, JSON.stringify({ v: v, })) + await backend.set(`${key}-secure-false`, JSON.stringify({ secure: false, v: v })) + + await expect(async () => await storage.secureGet(`${key}-no-secure`)).rejects.toThrowError("SecureGet has accessed to not secured data"); + await expect(async () => await storage.secureGet(`${key}-secure-false`)).rejects.toThrowError("SecureGet has accessed to not secured data"); + })); + }); + + test('should success if the data is secured', async () => { + fc.assert(fc.asyncProperty(fc.string(), fc.string(), async (key, value) => { + const v = await aes256.encrypt(JSON.stringify(value), passphrase); + await backend.set(key, JSON.stringify({ secure: true, v: v, })) + + await expect(storage.secureGet(key)).resolves.toEqual(value); + })); + }); + }); + + describe('get', () => { + test('should fail if the data is secured', async () => { + fc.assert(fc.asyncProperty(fc.string(), fc.string(), async (key, value) => { + const v = await aes256.encrypt(JSON.stringify(value), passphrase); + await backend.set(key, JSON.stringify({ secure: true, v: v })) + + await expect(async () => await storage.secureGet(key)).rejects.toThrowError("Can not access secure data"); + })); + }); + + test('should success if the data is not secured', async () => { + fc.assert(fc.asyncProperty(fc.string(), fc.string(), async (key, value) => { + await backend.set(key, JSON.stringify({ v: value, })); + await expect(storage.get(key)).resolves.toEqual(value); + })); + }); + }); + + describe('set', () => { + test('should store non-secured data', async () => { + fc.assert(fc.asyncProperty(fc.string(), fc.string(), async (key, value) => { + await storage.set(key, value); + + const raw = JSON.parse(await backend.get(key)); + expect(!!raw.secure).toEqual(false); + expect(raw.v).toEqual(value); + })); + }); + }); + + describe('secureSet', () => { + test('should store secured data', async () => { + fc.assert(fc.asyncProperty(fc.string(), fc.string(), async (key, value) => { + await storage.secureSet(key, value); + + const raw = JSON.parse(await backend.get(key)); + expect(raw.secure).toEqual(true); + expect(raw.v).not.toEqual(value); + })); + }); + }); +}) diff --git a/background/test/study.test.js b/background/test/study.test.js deleted file mode 100644 index a767188..0000000 --- a/background/test/study.test.js +++ /dev/null @@ -1,56 +0,0 @@ -import {hexZeroPad, joinSignature, serializeTransaction, splitSignature} from "ethers/lib/utils"; -const BN = require('bn.js'); -const EC = require("elliptic").ec; -const ec = new EC("secp256k1"); -const ethers = require("ethers") -const eccrypto = require("eccrypto") -import crypto from "crypto"; -import {BigNumber} from "ethers"; -import keccak256 from "keccak256"; - -//0x130283eE1f337E69236B9E5A844Ad14774450AAC -//022fd56e799cfa3db6230a8a18a1084eafaf44196c1f31dedc218e304f959139 -//ho -//0x21f3d880d38b195352c39f3ea13bb6b79380994d5fcab17e49a16bbd920e4dd445c0eeb3ac1568a3346300d5b1e734269bc655a75ce11b17448c0915614505401c - -const unsignedTx = 'ZDE6YWxkdTc6dHlwZV9pZHUxNTp0cmFuc2Zlcl9hc3NldDJ1Njp2YWx1ZXNkdTY6YW1vdW50bGR1MTM6ZGVjaW1hbFBsYWNlczE6AnU3Om1pbnRlcnNsMjA6R9CCoRXGPntYsVMtIOYxU46vrd5ldTY6dGlja2VydTM6TkNHZWkxMDBlZXU5OnJlY2lwaWVudDIwOllFSfxR0cBuiqjUralH+pHwvGvQdTY6c2VuZGVyMjA6EwKD7h8zfmkja55ahErRR3RFCqxlZWUxOmczMjpFgiUNDaM7BneahHXSg9XdIQxoO5uZnXTQP6xPWPprzjE6bmkyOWUxOnA2NToExhj966pCmc3EyQMXklv8Ii3E54RH0KcMYg0xHa6LfQ1vWAvV9E7amPFJWzCsVWHLVcE+oZ9AZ7yOS6fJomTMNzE6czIwOhMCg+4fM35pI2ueWoRK0Ud0RQqsMTp0dTI3OjIwMjItMDgtMzFUMTY6MTQ6MDEuNjkwMzczWjE6dWwyMDpZRUn8UdHAboqo1K2pR/qR8Lxr0DIwOhMCg+4fM35pI2ueWoRK0Ud0RQqsZWU=' -//unsignedTxId: [[233, 224, 251, 85, 177, 184, 15, 43, 121, 125, 201, 48, 51, 128, 6, 227, 251, 97, 194, 155, 133, 116, 132, 51, 171, 168, 219, 172, 105, 54, 255, 43] -//base64Sign: MEQCIB5GoEvpsq4P3OuJhouEO3+hXxAsIPDkTBJ5AL0n+KppAiA3kZf6+OvmRCMEbFu/MIPzWcxGEDUAD3d/JNPe0EKnlA== - -function pkToBuffer(pk) { - return Buffer.from(ethers.utils.arrayify(pk, {allowMissingPrefix: true})) -} - -// console.log('keccak', crypto.createHash('sha256').update('ZDE6YWxkdTc6dHlwZV9pZHUxNTp0cmFuc2Zlcl9hc3NldDJ1Njp2YWx1ZXNkdTY6YW1vdW50bGR1MTM6ZGVjaW1hbFBsYWNlczE6AnU3Om1pbnRlcnNsMjA6R9CCoRXGPntYsVMtIOYxU46vrd5ldTY6dGlja2VydTM6TkNHZWkxMDBlZXU5OnJlY2lwaWVudDIwOllFSfxR0cBuiqjUralH+pHwvGvQdTY6c2VuZGVyMjA6EwKD7h8zfmkja55ahErRR3RFCqxlZWUxOmczMjpFgiUNDaM7BneahHXSg9XdIQxoO5uZnXTQP6xPWPprzjE6bmkyOWUxOnA2NToExhj966pCmc3EyQMXklv8Ii3E54RH0KcMYg0xHa6LfQ1vWAvV9E7amPFJWzCsVWHLVcE+oZ9AZ7yOS6fJomTMNzE6czIwOhMCg+4fM35pI2ueWoRK0Ud0RQqsMTp0dTI3OjIwMjItMDgtMzFUMTY6MTQ6MDEuNjkwMzczWjE6dWwyMDpZRUn8UdHAboqo1K2pR/qR8Lxr0DIwOhMCg+4fM35pI2ueWoRK0Ud0RQqsZWU=', 'base64').digest()) -console.log('keccak', ethers.utils.base64.decode('ZDE6YWxkdTc6dHlwZV9pZHUxNTp0cmFuc2Zlcl9hc3NldDJ1Njp2YWx1ZXNkdTY6YW1vdW50bGR1MTM6ZGVjaW1hbFBsYWNlczE6AnU3Om1pbnRlcnNsMjA6R9CCoRXGPntYsVMtIOYxU46vrd5ldTY6dGlja2VydTM6TkNHZWkxMDBlZXU5OnJlY2lwaWVudDIwOllFSfxR0cBuiqjUralH+pHwvGvQdTY6c2VuZGVyMjA6EwKD7h8zfmkja55ahErRR3RFCqxlZWUxOmczMjpFgiUNDaM7BneahHXSg9XdIQxoO5uZnXTQP6xPWPprzjE6bmkyOWUxOnA2NToExhj966pCmc3EyQMXklv8Ii3E54RH0KcMYg0xHa6LfQ1vWAvV9E7amPFJWzCsVWHLVcE+oZ9AZ7yOS6fJomTMNzE6czIwOhMCg+4fM35pI2ueWoRK0Ud0RQqsMTp0dTI3OjIwMjItMDgtMzFUMTY6MTQ6MDEuNjkwMzczWjE6dWwyMDpZRUn8UdHAboqo1K2pR/qR8Lxr0DIwOhMCg+4fM35pI2ueWoRK0Ud0RQqsZWU=')) - -describe("test", () => { - test('encrypt & decrypt', async () => { - const pk = "0x022fd56e799cfa3db6230a8a18a1084eafaf44196c1f31dedc218e304f959139" - const wallet = new ethers.Wallet(pk) - const walletSignature = await wallet.signMessage('ho') - console.log('serialized', serializeTransaction({value:'0x1234'})) - wallet.signTransaction() - - const message = ethers.utils.hashMessage('ho') - const signature = ec.sign(ethers.utils.arrayify(message), pkToBuffer(pk), {canonical: true}) - const eccryptoSignature = joinSignature(splitSignature({ - recoveryParam: signature.recoveryParam, - r: hexZeroPad("0x" + signature.r.toString(16), 32), - s: hexZeroPad("0x" + signature.s.toString(16), 32), - })) - console.log(walletSignature == eccryptoSignature) - - await eccrypto.sign(pkToBuffer(pk), ethers.utils.arrayify(message)).then(sig => { - const eccryptoSign = ethers.utils.hexlify(sig) - const recoverSignature = splitSignature(walletSignature) - const randomSig = ec.sign('', eccrypto.generatePrivate(), {canonical: true}) - randomSig.r = new BN(recoverSignature.r.substring(2), 16) - randomSig.s = new BN(recoverSignature.s.substring(2), 16) - randomSig.recoveryParam = recoverSignature.recoveryParam - const recoverSign = ethers.utils.hexlify(randomSig.toDER()) - - console.log(eccryptoSign == recoverSign) - }) - }) -}) \ No newline at end of file diff --git a/background/test/utils/aes256.test.js b/background/test/utils/aes256.test.js deleted file mode 100644 index f923217..0000000 --- a/background/test/utils/aes256.test.js +++ /dev/null @@ -1,11 +0,0 @@ -import aes256 from "@/utils/aes256" - -describe("aes256 test", () => { - test('encrypt & decrypt', () => { - const passphrase = 'PASSPHRASE' - const plainText = 'Hello World' - const encrypted = aes256.encrypt(plainText, passphrase) - expect(() => aes256.decrypt(encrypted, 'Invalid Passphrase')).toThrowError() - expect(aes256.decrypt(encrypted, passphrase)).toEqual(plainText) - }) -}) \ No newline at end of file diff --git a/background/test/wallet/wallet.test.js b/background/test/wallet/wallet.test.js deleted file mode 100644 index 07eeb27..0000000 --- a/background/test/wallet/wallet.test.js +++ /dev/null @@ -1,57 +0,0 @@ -import Wallet from "@/wallet/wallet" -import Mock from "../mock" -import {ENCRYPTED_WALLET} from "@/constants/constants" -import crypto from "crypto"; -const ethers = require("ethers") - -Mock.mockGraphql() -Mock.mockStorage() -jest.setTimeout(1000 * 60) -const passphrase = 'pass' -describe("wallet.js", () => { - let wallet, address - beforeAll(async () => { - wallet = new Wallet(passphrase) - let w = ethers.Wallet.createRandom({locale: 'en'}) - address = w.address - let ew = await w.encrypt(passphrase) - wallet.storage.secureSet(ENCRYPTED_WALLET + address.toLowerCase(), ew) - }) - - test('Checking can call external', () => { - expect(wallet.canCallExternal('decryptWallet')).toBeFalsy() - }) - - test('Generate sequential wallet test', async () => { - let {address:address0} = await wallet.createSequentialWallet(address, 0) - let {address:address1} = await wallet.createSequentialWallet(address, 1) - expect(address0).toBe(address) - expect(address1).not.toBe(address) - expect(address1.length).toBe(address.length) - }) - - test('Generate private wallet test', async () => { - let privateKey = await wallet.getPrivateKey(address, passphrase) - let {address:address0} = await wallet.createPrivateKeyWallet(privateKey) - expect(address0).toBe(address) - }) - - test('Sign & Validate test', async () => { - let data = ['Hello World'] - let signature = await wallet.sign(address, data) - expect(await wallet.validateSignature(signature, data, address)).toBeTruthy() - }) - - - test('Mock send NCG test', async () => { - let receiver = '0x48BD02A8ADe581A55743646c8880F307F2e8e79D' - await expect(async () => await wallet.sendNCG(address, 'other', 100, 1)).rejects.toEqual("Invalid Nonce") - let result = await wallet.sendNCG(address, receiver, 100, await wallet.nextNonce(address)) - - expect(result['status']).toBe('STAGING') - expect(result['signer']).toBe(address) - expect(result['data']['sender']).toBe(address) - expect(result['data']['receiver']).toBe(receiver) - expect(result['data']['amount']).toBe(100) - }) -}) \ No newline at end of file diff --git a/background/tsconfig.json b/background/tsconfig.json index b4c6ec0..86b98b3 100644 --- a/background/tsconfig.json +++ b/background/tsconfig.json @@ -9,5 +9,5 @@ "@/*": ["./src/*"] } }, - "include": ["src"] + "include": ["src", "test"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 121c9fc..8e19947 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,27 +64,24 @@ importers: '@vue/test-utils': specifier: ^1.3.0 version: 1.3.6(vue-template-compiler@2.7.16)(vue@3.4.24(typescript@5.4.5)) - axios-mock-adapter: - specifier: ^1.20.0 - version: 1.22.0(axios@0.24.0) eslint: specifier: ^7.32.0 version: 7.32.0 eslint-plugin-vue: specifier: ^8.7.1 version: 8.7.1(eslint@7.32.0) - jest: - specifier: ^27.4.5 - version: 27.5.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) - jest-serializer-vue: - specifier: ^2.0.2 - version: 2.0.2 + fast-check: + specifier: ^3.19.0 + version: 3.19.0 typescript: specifier: ^5.4.5 version: 5.4.5 vite: specifier: ^5.2.8 version: 5.2.10(@types/node@20.12.7)(sass@1.75.0) + vitest: + specifier: ^1.6.0 + version: 1.6.0(@types/node@20.12.7)(jsdom@16.7.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(sass@1.75.0) vue-jest: specifier: ^3.0.7 version: 3.0.7(babel-core@7.0.0-bridge.0(@babel/core@7.24.4))(vue-template-compiler@2.7.16)(vue@3.4.24(typescript@5.4.5)) @@ -1502,6 +1499,10 @@ packages: node-notifier: optional: true + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/source-map@27.5.1': resolution: {integrity: sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -1737,6 +1738,9 @@ packages: '@shikijs/transformers@1.3.0': resolution: {integrity: sha512-3mlpg2I9CjhjE96dEWQOGeCWoPcyTov3s4aAsHmgvnTHa8MBknEnCQy8/xivJPSpD+olqOqIEoHnLfbNJK29AA==} + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + '@sindresorhus/is@4.6.0': resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} @@ -1973,6 +1977,21 @@ packages: vite: ^5.0.0 vue: ^3.2.25 + '@vitest/expect@1.6.0': + resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} + + '@vitest/runner@1.6.0': + resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} + + '@vitest/snapshot@1.6.0': + resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} + + '@vitest/spy@1.6.0': + resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} + + '@vitest/utils@1.6.0': + resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} + '@volar/language-core@2.2.1': resolution: {integrity: sha512-iHJAZKcYldZgyS8gx6DfIZApViVBeqbf6iPhqoZpG5A6F4zsZiFldKfwaKaBA3/wnOTWE2i8VUbXywI1WywCPg==} @@ -2178,6 +2197,10 @@ packages: resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} engines: {node: '>=0.4.0'} + acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + acorn@7.1.1: resolution: {integrity: sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==} engines: {node: '>=0.4.0'} @@ -2301,6 +2324,9 @@ packages: resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} engines: {node: '>=0.8'} + assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + astral-regex@1.0.0: resolution: {integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==} engines: {node: '>=4'} @@ -2341,11 +2367,6 @@ packages: aws4@1.12.0: resolution: {integrity: sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==} - axios-mock-adapter@1.22.0: - resolution: {integrity: sha512-dmI0KbkyAhntUR05YY96qg2H6gg0XMl2+qTW0xmYg6Up+BFBAJYRLROMXRdDEL06/Wqwa0TJThAYvFtSFdRCZw==} - peerDependencies: - axios: '>= 0.17.0' - axios@0.21.4: resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} @@ -2539,6 +2560,10 @@ packages: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + cacheable-lookup@5.0.4: resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} engines: {node: '>=10.6.0'} @@ -2583,6 +2608,10 @@ packages: caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + chai@4.4.1: + resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} + engines: {node: '>=4'} + chalk@1.1.3: resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} engines: {node: '>=0.10.0'} @@ -2611,6 +2640,9 @@ packages: chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -2729,6 +2761,9 @@ packages: resolution: {integrity: sha512-P7X+QL9Hb9B/c8HI5BFFKmjgBu2XpQuF98WZ9XkO+dBGgk5XgwiQz7o1SmpglNWId3581UcS0SFAWfoIhMHPfg==} engines: {node: '>=0.10.0'} + confbox@0.1.7: + resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} + config-chain@1.1.13: resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} @@ -2903,6 +2938,10 @@ packages: dedent@0.7.0: resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} + deep-eql@4.1.3: + resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + engines: {node: '>=6'} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -2952,6 +2991,10 @@ packages: resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + 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'} @@ -3212,6 +3255,9 @@ packages: estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -3266,6 +3312,10 @@ packages: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + exit@0.1.2: resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} engines: {node: '>= 0.8.0'} @@ -3304,6 +3354,10 @@ packages: resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} engines: {'0': node >=0.6.0} + fast-check@3.19.0: + resolution: {integrity: sha512-CO2JX/8/PT9bDGO1iXa5h5ey1skaKI1dvecERyhH4pp3PGjwd3KIjMAXEg79Ps9nclsdt4oPbfqiAnLU0EwrAQ==} + engines: {node: '>=8.0.0'} + fast-decode-uri-component@1.0.1: resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} @@ -3459,6 +3513,9 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + 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'} @@ -3475,6 +3532,10 @@ packages: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + getpass@0.1.7: resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} @@ -3681,6 +3742,10 @@ packages: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -3774,10 +3839,6 @@ packages: is-buffer@1.1.6: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} - is-buffer@2.0.5: - resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} - engines: {node: '>=4'} - is-builtin-module@3.2.1: resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} engines: {node: '>=6'} @@ -3856,6 +3917,10 @@ packages: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + is-typed-array@1.1.13: resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} engines: {node: '>= 0.4'} @@ -4089,6 +4154,9 @@ 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@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} hasBin: true @@ -4205,6 +4273,10 @@ packages: enquirer: optional: true + local-pkg@0.5.0: + resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} + engines: {node: '>=14'} + locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -4237,6 +4309,9 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + lower-case-first@2.0.2: resolution: {integrity: sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==} @@ -4336,6 +4411,10 @@ packages: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + mimic-response@1.0.1: resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} engines: {node: '>=4'} @@ -4405,6 +4484,9 @@ packages: engines: {node: '>=10'} hasBin: true + mlly@1.7.0: + resolution: {integrity: sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==} + mock-fs@4.14.0: resolution: {integrity: sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw==} @@ -4534,6 +4616,10 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} @@ -4579,6 +4665,10 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + optimism@0.18.0: resolution: {integrity: sha512-tGn8+REwLRNFnb9WmcY5IfpOqeX2kpaYJ1s6Ae3mn12AeydLkR3j+jSCmVQFoXqU8D41PAJ1RG1rCRNWmNZVmQ==} @@ -4614,6 +4704,10 @@ 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'} @@ -4684,6 +4778,10 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -4706,6 +4804,12 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + pbkdf2@3.1.2: resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} engines: {node: '>=0.12'} @@ -4747,6 +4851,9 @@ 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==} + possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} @@ -4807,6 +4914,10 @@ packages: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + pretty@2.0.0: resolution: {integrity: sha512-G9xUchgTEiNpormdYBl+Pha50gOUovT18IvAe7EYMZ1/f9W/WWMPRn+xI68yXNMUk3QXHDwo/1wV/4NejVNe1w==} engines: {node: '>=0.10.0'} @@ -4853,6 +4964,9 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + pvtsutils@1.3.5: resolution: {integrity: sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==} @@ -4904,6 +5018,9 @@ packages: react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + react-refresh@0.14.0: resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} engines: {node: '>=0.10.0'} @@ -5167,6 +5284,9 @@ packages: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} engines: {node: '>= 0.4'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -5255,10 +5375,16 @@ packages: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} + 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==} + streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} @@ -5317,6 +5443,10 @@ packages: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + strip-hex-prefix@1.0.0: resolution: {integrity: sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==} engines: {node: '>=6.5.0', npm: '>=3'} @@ -5329,6 +5459,9 @@ 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'} @@ -5419,6 +5552,17 @@ packages: resolution: {integrity: sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==} engines: {node: '>=0.10.0'} + tinybench@2.8.0: + resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==} + + tinypool@0.8.4: + resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} + engines: {node: '>=14.0.0'} + + tinyspy@2.2.1: + resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} + engines: {node: '>=14.0.0'} + title-case@3.0.3: resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==} @@ -5539,6 +5683,9 @@ packages: ua-parser-js@1.0.37: resolution: {integrity: sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==} + ufo@1.5.3: + resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} + ultron@1.1.1: resolution: {integrity: sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==} @@ -5647,6 +5794,11 @@ packages: resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} engines: {'0': node >=0.6.0} + vite-node@1.6.0: + resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + vite@5.2.10: resolution: {integrity: sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw==} engines: {node: ^18.0.0 || >=20.0.0} @@ -5687,6 +5839,31 @@ packages: postcss: optional: true + vitest@1.6.0: + resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} + 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 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vue-component-type-helpers@2.0.14: resolution: {integrity: sha512-DInfgOyXlMyliyqAAD9frK28tTfch0+tMi4qoWJcZlRxUf+NFAtraJBnAsKLep+FOyLMiajkhfyEb3xLK08i7w==} @@ -5918,6 +6095,11 @@ packages: engines: {node: '>= 8'} hasBin: true + why-is-node-running@2.2.2: + resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} + engines: {node: '>=8'} + hasBin: true + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -6075,6 +6257,10 @@ 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'} + zen-observable-ts@1.2.5: resolution: {integrity: sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==} @@ -7766,6 +7952,10 @@ snapshots: transitivePeerDependencies: - supports-color + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.8 + '@jest/source-map@27.5.1': dependencies: callsites: 3.1.0 @@ -8008,6 +8198,8 @@ snapshots: dependencies: shiki: 1.3.0 + '@sinclair/typebox@0.27.8': {} + '@sindresorhus/is@4.6.0': {} '@sinonjs/commons@1.8.6': @@ -8339,6 +8531,35 @@ snapshots: vite: 5.2.10(@types/node@20.12.7)(sass@1.75.0) vue: 3.4.24(typescript@5.4.5) + '@vitest/expect@1.6.0': + dependencies: + '@vitest/spy': 1.6.0 + '@vitest/utils': 1.6.0 + chai: 4.4.1 + + '@vitest/runner@1.6.0': + dependencies: + '@vitest/utils': 1.6.0 + p-limit: 5.0.0 + pathe: 1.1.2 + + '@vitest/snapshot@1.6.0': + dependencies: + magic-string: 0.30.10 + pathe: 1.1.2 + pretty-format: 29.7.0 + + '@vitest/spy@1.6.0': + dependencies: + tinyspy: 2.2.1 + + '@vitest/utils@1.6.0': + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + '@volar/language-core@2.2.1': dependencies: '@volar/source-map': 2.2.1 @@ -8579,6 +8800,8 @@ snapshots: acorn-walk@7.2.0: {} + acorn-walk@8.3.2: {} + acorn@7.1.1: {} acorn@7.4.1: {} @@ -8699,6 +8922,8 @@ snapshots: assert-plus@1.0.0: {} + assertion-error@1.1.0: {} + astral-regex@1.0.0: {} astral-regex@2.0.0: {} @@ -8729,12 +8954,6 @@ snapshots: aws4@1.12.0: {} - axios-mock-adapter@1.22.0(axios@0.24.0): - dependencies: - axios: 0.24.0 - fast-deep-equal: 3.1.3 - is-buffer: 2.0.5 - axios@0.21.4: dependencies: follow-redirects: 1.15.6 @@ -9038,6 +9257,8 @@ snapshots: bytes@3.1.2: {} + cac@6.7.14: {} + cacheable-lookup@5.0.4: {} cacheable-lookup@6.1.0: {} @@ -9083,6 +9304,16 @@ snapshots: caseless@0.12.0: {} + chai@4.4.1: + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.3 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.0.8 + chalk@1.1.3: dependencies: ansi-styles: 2.2.1 @@ -9147,6 +9378,10 @@ snapshots: chardet@0.7.0: {} + check-error@1.0.3: + dependencies: + get-func-name: 2.0.2 + chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -9261,6 +9496,8 @@ snapshots: is-whitespace: 0.3.0 kind-of: 3.2.2 + confbox@0.1.7: {} + config-chain@1.1.13: dependencies: ini: 1.3.8 @@ -9437,6 +9674,10 @@ snapshots: dedent@0.7.0: {} + deep-eql@4.1.3: + dependencies: + type-detect: 4.0.8 + deep-is@0.1.4: {} deepmerge@4.3.1: {} @@ -9469,6 +9710,8 @@ snapshots: diff-sequences@27.5.1: {} + diff-sequences@29.6.3: {} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 @@ -9879,6 +10122,10 @@ snapshots: estree-walker@2.0.2: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.5 + esutils@2.0.3: {} etag@1.8.1: {} @@ -10022,6 +10269,18 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 + execa@8.0.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + exit@0.1.2: {} expect@27.5.1: @@ -10091,6 +10350,10 @@ snapshots: extsprintf@1.3.0: {} + fast-check@3.19.0: + dependencies: + pure-rand: 6.1.0 + fast-decode-uri-component@1.0.1: {} fast-deep-equal@3.1.3: {} @@ -10258,6 +10521,8 @@ snapshots: get-caller-file@2.0.5: {} + get-func-name@2.0.2: {} + get-intrinsic@1.2.4: dependencies: es-errors: 1.3.0 @@ -10274,6 +10539,8 @@ snapshots: get-stream@6.0.1: {} + get-stream@8.0.1: {} + getpass@0.1.7: dependencies: assert-plus: 1.0.0 @@ -10541,6 +10808,8 @@ snapshots: human-signals@2.1.0: {} + human-signals@5.0.0: {} + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -10647,8 +10916,6 @@ snapshots: is-buffer@1.1.6: {} - is-buffer@2.0.5: {} - is-builtin-module@3.2.1: dependencies: builtin-modules: 3.3.0 @@ -10705,6 +10972,8 @@ snapshots: is-stream@2.0.1: {} + is-stream@3.0.0: {} + is-typed-array@1.1.13: dependencies: which-typed-array: 1.1.15 @@ -11155,6 +11424,8 @@ snapshots: js-tokens@4.0.0: {} + js-tokens@9.0.0: {} + js-yaml@3.14.1: dependencies: argparse: 1.0.10 @@ -11290,6 +11561,11 @@ snapshots: optionalDependencies: enquirer: 2.4.1 + local-pkg@0.5.0: + dependencies: + mlly: 1.7.0 + pkg-types: 1.1.1 + locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -11322,6 +11598,10 @@ snapshots: dependencies: js-tokens: 4.0.0 + loupe@2.3.7: + dependencies: + get-func-name: 2.0.2 + lower-case-first@2.0.2: dependencies: tslib: 2.6.2 @@ -11399,6 +11679,8 @@ snapshots: mimic-fn@2.1.0: {} + mimic-fn@4.0.0: {} + mimic-response@1.0.1: {} mimic-response@3.1.0: {} @@ -11458,6 +11740,13 @@ snapshots: mkdirp@3.0.1: {} + mlly@1.7.0: + dependencies: + acorn: 8.11.3 + pathe: 1.1.2 + pkg-types: 1.1.1 + ufo: 1.5.3 + mock-fs@4.14.0: {} moment@2.30.1: {} @@ -11563,6 +11852,10 @@ snapshots: dependencies: path-key: 3.1.1 + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + nth-check@2.1.1: dependencies: boolbase: 1.0.0 @@ -11602,6 +11895,10 @@ snapshots: dependencies: mimic-fn: 2.1.0 + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + optimism@0.18.0: dependencies: '@wry/caches': 1.0.1 @@ -11653,6 +11950,10 @@ 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 @@ -11717,6 +12018,8 @@ snapshots: path-key@3.1.1: {} + path-key@4.0.0: {} + path-parse@1.0.7: {} path-root-regex@0.1.2: {} @@ -11734,6 +12037,10 @@ snapshots: path-type@4.0.0: {} + pathe@1.1.2: {} + + pathval@1.1.1: {} + pbkdf2@3.1.2: dependencies: create-hash: 1.2.0 @@ -11766,6 +12073,12 @@ snapshots: dependencies: find-up: 4.1.0 + pkg-types@1.1.1: + dependencies: + confbox: 0.1.7 + mlly: 1.7.0 + pathe: 1.1.2 + possible-typed-array-names@1.0.0: {} postcss-import@15.1.0(postcss@8.4.38): @@ -11817,6 +12130,12 @@ snapshots: ansi-styles: 5.2.0 react-is: 17.0.2 + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + pretty@2.0.0: dependencies: condense-newlines: 0.2.1 @@ -11862,6 +12181,8 @@ snapshots: punycode@2.3.1: {} + pure-rand@6.1.0: {} + pvtsutils@1.3.5: dependencies: tslib: 2.6.2 @@ -11909,6 +12230,8 @@ snapshots: react-is@17.0.2: {} + react-is@18.3.1: {} + react-refresh@0.14.0: {} react@18.2.0: @@ -12215,6 +12538,8 @@ snapshots: get-intrinsic: 1.2.4 object-inspect: 1.13.1 + siginfo@2.0.0: {} + signal-exit@3.0.7: {} signal-exit@4.1.0: {} @@ -12305,8 +12630,12 @@ snapshots: dependencies: escape-string-regexp: 2.0.0 + stackback@0.0.2: {} + statuses@2.0.1: {} + std-env@3.7.0: {} + streamsearch@1.1.0: {} strict-uri-encode@1.1.0: {} @@ -12362,6 +12691,8 @@ snapshots: strip-final-newline@2.0.0: {} + strip-final-newline@3.0.0: {} + strip-hex-prefix@1.0.0: dependencies: is-hex-prefixed: 1.0.0 @@ -12370,6 +12701,10 @@ 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 @@ -12508,6 +12843,12 @@ snapshots: timed-out@4.0.1: {} + tinybench@2.8.0: {} + + tinypool@0.8.4: {} + + tinyspy@2.2.1: {} + title-case@3.0.3: dependencies: tslib: 2.6.2 @@ -12610,6 +12951,8 @@ snapshots: ua-parser-js@1.0.37: {} + ufo@1.5.3: {} + ultron@1.1.1: {} unc-path-regex@0.1.2: {} @@ -12701,6 +13044,23 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 + vite-node@1.6.0(@types/node@20.12.7)(sass@1.75.0): + dependencies: + cac: 6.7.14 + debug: 4.3.4 + pathe: 1.1.2 + picocolors: 1.0.0 + vite: 5.2.10(@types/node@20.12.7)(sass@1.75.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + vite@5.2.10(@types/node@20.12.7)(sass@1.75.0): dependencies: esbuild: 0.20.2 @@ -12757,6 +13117,40 @@ snapshots: - typescript - universal-cookie + vitest@1.6.0(@types/node@20.12.7)(jsdom@16.7.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(sass@1.75.0): + 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.2 + chai: 4.4.1 + debug: 4.3.4 + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.10 + pathe: 1.1.2 + picocolors: 1.0.0 + std-env: 3.7.0 + strip-literal: 2.1.0 + tinybench: 2.8.0 + tinypool: 0.8.4 + vite: 5.2.10(@types/node@20.12.7)(sass@1.75.0) + vite-node: 1.6.0(@types/node@20.12.7)(sass@1.75.0) + why-is-node-running: 2.2.2 + optionalDependencies: + '@types/node': 20.12.7 + jsdom: 16.7.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + vue-component-type-helpers@2.0.14: {} vue-demi@0.14.7(vue@3.4.24(typescript@5.4.5)): @@ -13133,6 +13527,11 @@ snapshots: dependencies: isexe: 2.0.0 + why-is-node-running@2.2.2: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + word-wrap@1.2.5: {} wrap-ansi@6.2.0: @@ -13281,6 +13680,8 @@ snapshots: yocto-queue@0.1.0: {} + yocto-queue@1.0.0: {} + zen-observable-ts@1.2.5: dependencies: zen-observable: 0.8.15