1
0
Эх сурвалжийг харах

test(core): Set up vitest for e2e testing

Michael Bromley 2 жил өмнө
parent
commit
b5bac42e54
89 өөрчлөгдсөн 854 нэмэгдсэн , 220 устгасан
  1. 1 2
      e2e-common/get-package-dir.js
  2. 2 0
      e2e-common/jest-config.js
  3. 3 21
      e2e-common/test-config.ts
  4. 2 0
      e2e-common/tsconfig.e2e.json
  5. 28 0
      e2e-common/vitest.config.ts
  6. 4 1
      package.json
  7. 3 3
      packages/core/e2e/__snapshots__/administrator.e2e-spec.ts.snap
  8. 5 5
      packages/core/e2e/__snapshots__/collection.e2e-spec.ts.snap
  9. 2 2
      packages/core/e2e/__snapshots__/facet.e2e-spec.ts.snap
  10. 6 6
      packages/core/e2e/__snapshots__/import.e2e-spec.ts.snap
  11. 3 3
      packages/core/e2e/__snapshots__/product.e2e-spec.ts.snap
  12. 7 7
      packages/core/e2e/__snapshots__/promotion.e2e-spec.ts.snap
  13. 1 0
      packages/core/e2e/active-order-strategy.e2e-spec.ts
  14. 1 0
      packages/core/e2e/administrator.e2e-spec.ts
  15. 7 6
      packages/core/e2e/apollo-server-plugin.e2e-spec.ts
  16. 1 0
      packages/core/e2e/asset-channel.e2e-spec.ts
  17. 1 0
      packages/core/e2e/asset.e2e-spec.ts
  18. 1 0
      packages/core/e2e/auth.e2e-spec.ts
  19. 1 0
      packages/core/e2e/authentication-strategy.e2e-spec.ts
  20. 1 0
      packages/core/e2e/channel.e2e-spec.ts
  21. 3 1
      packages/core/e2e/collection.e2e-spec.ts
  22. 1 0
      packages/core/e2e/configurable-operation.e2e-spec.ts
  23. 1 0
      packages/core/e2e/country.e2e-spec.ts
  24. 7 6
      packages/core/e2e/custom-field-relations.e2e-spec.ts
  25. 3 1
      packages/core/e2e/custom-fields.e2e-spec.ts
  26. 1 0
      packages/core/e2e/custom-permissions.e2e-spec.ts
  27. 1 0
      packages/core/e2e/customer-channel.e2e-spec.ts
  28. 1 0
      packages/core/e2e/customer-group.e2e-spec.ts
  29. 4 2
      packages/core/e2e/customer.e2e-spec.ts
  30. 1 0
      packages/core/e2e/database-transactions.e2e-spec.ts
  31. 1 0
      packages/core/e2e/default-search-plugin-uuids.e2e-spec.ts
  32. 2 6
      packages/core/e2e/default-search-plugin.e2e-spec.ts
  33. 1 0
      packages/core/e2e/draft-order.e2e-spec.ts
  34. 1 0
      packages/core/e2e/entity-hydrator.e2e-spec.ts
  35. 1 0
      packages/core/e2e/entity-id-strategy.e2e-spec.ts
  36. 1 0
      packages/core/e2e/entity-prefix.e2e-spec.ts
  37. 1 0
      packages/core/e2e/entity-uuid-strategy.e2e-spec.ts
  38. 1 0
      packages/core/e2e/facet.e2e-spec.ts
  39. 3 2
      packages/core/e2e/fixtures/test-payment-methods.ts
  40. 2 1
      packages/core/e2e/fixtures/test-plugins/issue-1636-1664/issue-1636-1664-plugin.ts
  41. 3 2
      packages/core/e2e/fixtures/test-plugins/transaction-test-plugin.ts
  42. 7 5
      packages/core/e2e/fulfillment-process.e2e-spec.ts
  43. 1 0
      packages/core/e2e/global-settings.e2e-spec.ts
  44. 1 0
      packages/core/e2e/import.e2e-spec.ts
  45. 1 0
      packages/core/e2e/job-queue.e2e-spec.ts
  46. 6 4
      packages/core/e2e/lifecycle.e2e-spec.ts
  47. 1 0
      packages/core/e2e/list-query-builder.e2e-spec.ts
  48. 1 0
      packages/core/e2e/localization.e2e-spec.ts
  49. 2 2
      packages/core/e2e/money-strategy.e2e-spec.ts
  50. 3 1
      packages/core/e2e/order-changed-price-handling.e2e-spec.ts
  51. 1 0
      packages/core/e2e/order-channel.e2e-spec.ts
  52. 3 1
      packages/core/e2e/order-fulfillment.e2e-spec.ts
  53. 1 0
      packages/core/e2e/order-item-price-calculation-strategy.e2e-spec.ts
  54. 1 0
      packages/core/e2e/order-merge.e2e-spec.ts
  55. 1 0
      packages/core/e2e/order-modification.e2e-spec.ts
  56. 7 5
      packages/core/e2e/order-process.e2e-spec.ts
  57. 1 0
      packages/core/e2e/order-promotion.e2e-spec.ts
  58. 1 0
      packages/core/e2e/order-taxes.e2e-spec.ts
  59. 2 1
      packages/core/e2e/order.e2e-spec.ts
  60. 1 0
      packages/core/e2e/parallel-transactions.e2e-spec.ts
  61. 3 1
      packages/core/e2e/payment-method.e2e-spec.ts
  62. 7 5
      packages/core/e2e/payment-process.e2e-spec.ts
  63. 3 1
      packages/core/e2e/plugin.e2e-spec.ts
  64. 1 0
      packages/core/e2e/populate.e2e-spec.ts
  65. 1 0
      packages/core/e2e/product-channel.e2e-spec.ts
  66. 1 0
      packages/core/e2e/product-option.e2e-spec.ts
  67. 1 0
      packages/core/e2e/product.e2e-spec.ts
  68. 1 0
      packages/core/e2e/promotion.e2e-spec.ts
  69. 1 0
      packages/core/e2e/relations-decorator.e2e-spec.ts
  70. 102 82
      packages/core/e2e/role.e2e-spec.ts
  71. 6 4
      packages/core/e2e/session-management.e2e-spec.ts
  72. 5 3
      packages/core/e2e/shipping-method-eligibility.e2e-spec.ts
  73. 1 0
      packages/core/e2e/shipping-method.e2e-spec.ts
  74. 14 12
      packages/core/e2e/shop-auth.e2e-spec.ts
  75. 1 0
      packages/core/e2e/shop-catalog.e2e-spec.ts
  76. 1 0
      packages/core/e2e/shop-customer.e2e-spec.ts
  77. 4 3
      packages/core/e2e/shop-order.e2e-spec.ts
  78. 1 0
      packages/core/e2e/stock-control-multi-location.e2e-spec.ts
  79. 1 0
      packages/core/e2e/stock-control.e2e-spec.ts
  80. 1 0
      packages/core/e2e/tag.e2e-spec.ts
  81. 1 0
      packages/core/e2e/tax-category.e2e-spec.ts
  82. 1 0
      packages/core/e2e/tax-rate.e2e-spec.ts
  83. 1 0
      packages/core/e2e/translations.e2e-spec.ts
  84. 1 0
      packages/core/e2e/utils/assert-throws-with-message.ts
  85. 1 0
      packages/core/e2e/utils/await-running-jobs.ts
  86. 1 0
      packages/core/e2e/utils/test-order-utils.ts
  87. 1 0
      packages/core/e2e/zone.e2e-spec.ts
  88. 5 4
      packages/core/package.json
  89. 524 9
      yarn.lock

+ 1 - 2
e2e-common/get-package-dir.js

@@ -5,13 +5,12 @@ const path = require('path');
  */
 function getPackageDir() {
     const packageArg = process.env.packageArg || process.argv.find(arg => arg.startsWith('--package='));
-
     if (!packageArg) {
         console.error('No package specified! Please pass --package=<packageDirName>');
         process.exit(1);
     }
     const packageDirname = packageArg.split('=')[1];
-    return path.join(__dirname, '../packages', packageDirname, 'e2e');
+    return path.join(__dirname, '../packages', packageDirname ?? packageArg, 'e2e');
 }
 
 module.exports = { getPackageDir };

+ 2 - 0
e2e-common/jest-config.js

@@ -13,6 +13,7 @@ module.exports = {
     rootDir: packageDirname,
     testRegex: '.e2e-spec.ts$',
     maxWorkers: process.env.CI ? 1 : 3,
+    extensionsToTreatAsEsm: ['.ts'],
     transform: {
         '^.+\\.ts$': [
             'ts-jest',
@@ -20,6 +21,7 @@ module.exports = {
                 tsconfig: '<rootDir>/config/tsconfig.e2e.json',
                 diagnostics: false,
                 isolatedModules: true,
+                useESM: true,
             },
         ],
     },

+ 3 - 21
e2e-common/test-config.ts

@@ -9,6 +9,7 @@ import {
 import fs from 'fs-extra';
 import path from 'path';
 import { DataSourceOptions } from 'typeorm';
+import { fileURLToPath } from 'url';
 
 import { getPackageDir } from './get-package-dir';
 
@@ -34,28 +35,9 @@ registerInitializer('postgres', new PostgresInitializer());
 registerInitializer('mysql', new MysqlInitializer());
 registerInitializer('mariadb', new MysqlInitializer());
 
-/**
- * Increase default timeout in CI because occasionally valid tests fail due to
- * timeouts.
- */
-if (process.env.CI) {
-    jest.setTimeout(30 * 1000);
-} else {
-    jest.setTimeout(15 * 1000);
-}
-
-/**
- * For local debugging of the e2e tests, we set a very long timeout value otherwise tests will
- * automatically fail for going over the 5 second default timeout.
- */
-if (process.env.E2E_DEBUG) {
-    // tslint:disable-next-line:no-console
-    console.log('E2E_DEBUG', process.env.E2E_DEBUG, ' - setting long timeout');
-    jest.setTimeout(1800 * 1000);
-}
-
 export const testConfig = () => {
-    const portsFile = path.join(__dirname, 'ports.json');
+    // @ts-ignore
+    const portsFile = fileURLToPath(new URL('ports.json', import.meta.url));
     fs.ensureFileSync(portsFile);
     let usedPorts: number[];
     try {

+ 2 - 0
e2e-common/tsconfig.e2e.json

@@ -7,6 +7,8 @@
     "inlineSourceMap": false,
     "sourceMap": true,
     "allowSyntheticDefaultImports": true,
+    "experimentalDecorators": true,
+    "emitDecoratorMetadata": true,
     "esModuleInterop": true,
     "allowJs": false,
     "diagnostics": false

+ 28 - 0
e2e-common/vitest.config.ts

@@ -0,0 +1,28 @@
+import path from 'path';
+import swc from 'unplugin-swc';
+import { defineConfig } from 'vitest/config';
+
+export default defineConfig({
+    test: {
+        include: '**/*.e2e-spec.ts',
+        /**
+         * For local debugging of the e2e tests, we set a very long timeout value otherwise tests will
+         * automatically fail for going over the 5 second default timeout.
+         */
+        testTimeout: process.env.E2E_DEBUG ? 1800 * 1000 : process.env.CI ? 30 * 1000 : 15 * 1000,
+        // threads: false,
+        // singleThread: true,
+        // reporters: ['verbose'],
+        typecheck: {
+            tsconfig: path.join(__dirname, 'tsconfig.e2e.json'),
+        },
+    },
+    plugins: [
+        // SWC required to support decorators used in test plugins
+        // See https://github.com/vitest-dev/vitest/issues/708#issuecomment-1118628479
+        // Vite plugin
+        swc.vite(),
+        // Rollup plugin
+        swc.rollup() as any,
+    ],
+});

+ 4 - 1
package.json

@@ -38,6 +38,7 @@
     "@graphql-codegen/typescript": "3.0.1",
     "@graphql-codegen/typescript-operations": "3.0.1",
     "@graphql-tools/schema": "^9.0.17",
+    "@swc/core": "^1.3.38",
     "@types/jest": "^29.4.0",
     "@types/klaw-sync": "^6.0.0",
     "@types/node": "^14.14.31",
@@ -54,7 +55,9 @@
     "ts-jest": "^29.0.5",
     "ts-node": "^10.9.1",
     "tslint": "^6.1.3",
-    "typescript": "4.9.5"
+    "typescript": "4.9.5",
+    "unplugin-swc": "^1.3.2",
+    "vitest": "^0.29.2"
   },
   "resolutions": {
     "npm-packlist": "1.1.12"

+ 3 - 3
packages/core/e2e/__snapshots__/administrator.e2e-spec.ts.snap

@@ -1,6 +1,6 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
-exports[`Administrator resolver createAdministrator 1`] = `
+exports[`Administrator resolver > createAdministrator 1`] = `
 {
   "emailAddress": "test@test.com",
   "firstName": "First",
@@ -110,7 +110,7 @@ exports[`Administrator resolver createAdministrator 1`] = `
 }
 `;
 
-exports[`Administrator resolver updateAdministrator 1`] = `
+exports[`Administrator resolver > updateAdministrator 1`] = `
 {
   "emailAddress": "new-email",
   "firstName": "new first",

+ 5 - 5
packages/core/e2e/__snapshots__/collection.e2e-spec.ts.snap

@@ -1,6 +1,6 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
-exports[`Collection resolver createCollection creates a root collection 1`] = `
+exports[`Collection resolver > createCollection > creates a root collection 1`] = `
 {
   "assets": [
     {
@@ -38,7 +38,7 @@ exports[`Collection resolver createCollection creates a root collection 1`] = `
       "args": [
         {
           "name": "facetValueIds",
-          "value": "["T_1"]",
+          "value": "[\\"T_1\\"]",
         },
         {
           "name": "containsAny",
@@ -69,7 +69,7 @@ exports[`Collection resolver createCollection creates a root collection 1`] = `
 }
 `;
 
-exports[`Collection resolver updateCollection updates with assets 1`] = `
+exports[`Collection resolver > updateCollection > updates with assets 1`] = `
 {
   "assets": [
     {
@@ -107,7 +107,7 @@ exports[`Collection resolver updateCollection updates with assets 1`] = `
       "args": [
         {
           "name": "facetValueIds",
-          "value": "["T_3"]",
+          "value": "[\\"T_3\\"]",
         },
         {
           "name": "containsAny",

+ 2 - 2
packages/core/e2e/__snapshots__/facet.e2e-spec.ts.snap

@@ -1,6 +1,6 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
-exports[`Facet resolver createFacet 1`] = `
+exports[`Facet resolver > createFacet 1`] = `
 {
   "code": "speaker-type",
   "id": "T_2",

+ 6 - 6
packages/core/e2e/__snapshots__/import.e2e-spec.ts.snap

@@ -1,6 +1,6 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
-exports[`Import resolver imports products 1`] = `
+exports[`Import resolver > imports products 1`] = `
 {
   "assets": [
     {
@@ -119,7 +119,7 @@ exports[`Import resolver imports products 1`] = `
 }
 `;
 
-exports[`Import resolver imports products 2`] = `
+exports[`Import resolver > imports products 2`] = `
 {
   "assets": [],
   "customFields": {
@@ -168,7 +168,7 @@ exports[`Import resolver imports products 2`] = `
 }
 `;
 
-exports[`Import resolver imports products 3`] = `
+exports[`Import resolver > imports products 3`] = `
 {
   "assets": [],
   "customFields": {
@@ -262,7 +262,7 @@ exports[`Import resolver imports products 3`] = `
 }
 `;
 
-exports[`Import resolver imports products 4`] = `
+exports[`Import resolver > imports products 4`] = `
 {
   "assets": [],
   "customFields": {
@@ -403,7 +403,7 @@ exports[`Import resolver imports products 4`] = `
 }
 `;
 
-exports[`Import resolver imports products with multiple languages 1`] = `
+exports[`Import resolver > imports products with multiple languages 1`] = `
 {
   "assets": [],
   "customFields": {

+ 3 - 3
packages/core/e2e/__snapshots__/product.e2e-spec.ts.snap

@@ -1,6 +1,6 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
-exports[`Product resolver product mutation createProduct creates a new Product 1`] = `
+exports[`Product resolver > product mutation > createProduct creates a new Product 1`] = `
 {
   "assets": [],
   "channels": [
@@ -22,7 +22,7 @@ exports[`Product resolver product mutation createProduct creates a new Product 1
 }
 `;
 
-exports[`Product resolver product query returns expected properties 1`] = `
+exports[`Product resolver > product query > returns expected properties 1`] = `
 {
   "assets": [
     {

+ 7 - 7
packages/core/e2e/__snapshots__/promotion.e2e-spec.ts.snap

@@ -1,6 +1,6 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
-exports[`Promotion resolver adjustmentOperations 1`] = `
+exports[`Promotion resolver > adjustmentOperations 1`] = `
 [
   {
     "args": [
@@ -16,7 +16,7 @@ exports[`Promotion resolver adjustmentOperations 1`] = `
 ]
 `;
 
-exports[`Promotion resolver adjustmentOperations 2`] = `
+exports[`Promotion resolver > adjustmentOperations 2`] = `
 [
   {
     "args": [
@@ -43,14 +43,14 @@ exports[`Promotion resolver adjustmentOperations 2`] = `
 ]
 `;
 
-exports[`Promotion resolver createPromotion 1`] = `
+exports[`Promotion resolver > createPromotion 1`] = `
 {
   "actions": [
     {
       "args": [
         {
           "name": "facetValueIds",
-          "value": "["T_1"]",
+          "value": "[\\"T_1\\"]",
         },
       ],
       "code": "promo_action",
@@ -75,14 +75,14 @@ exports[`Promotion resolver createPromotion 1`] = `
 }
 `;
 
-exports[`Promotion resolver updatePromotion 1`] = `
+exports[`Promotion resolver > updatePromotion 1`] = `
 {
   "actions": [
     {
       "args": [
         {
           "name": "facetValueIds",
-          "value": "["T_1"]",
+          "value": "[\\"T_1\\"]",
         },
       ],
       "code": "promo_action",

+ 1 - 0
packages/core/e2e/active-order-strategy.e2e-spec.ts

@@ -3,6 +3,7 @@ import { mergeConfig, orderPercentageDiscount } from '@vendure/core';
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/administrator.e2e-spec.ts

@@ -3,6 +3,7 @@ import { createTestEnvironment } from '@vendure/testing';
 import { fail } from 'assert';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 7 - 6
packages/core/e2e/apollo-server-plugin.e2e-spec.ts

@@ -7,20 +7,21 @@ import {
 } from 'apollo-server-plugin-base';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
 import { createTestEnvironment } from '../../testing/lib/create-test-environment';
 
 class MyApolloServerPlugin implements ApolloServerPlugin {
-    static serverWillStartFn = jest.fn();
-    static requestDidStartFn = jest.fn();
-    static willSendResponseFn = jest.fn();
+    static serverWillStartFn = vi.fn();
+    static requestDidStartFn = vi.fn();
+    static willSendResponseFn = vi.fn();
 
     static reset() {
-        this.serverWillStartFn = jest.fn();
-        this.requestDidStartFn = jest.fn();
-        this.willSendResponseFn = jest.fn();
+        this.serverWillStartFn = vi.fn();
+        this.requestDidStartFn = vi.fn();
+        this.willSendResponseFn = vi.fn();
     }
 
     serverWillStart(service: GraphQLServiceContext): Promise<void> | void {

+ 1 - 0
packages/core/e2e/asset-channel.e2e-spec.ts

@@ -2,6 +2,7 @@
 import { createTestEnvironment, E2E_DEFAULT_CHANNEL_TOKEN } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/asset.e2e-spec.ts

@@ -5,6 +5,7 @@ import { mergeConfig } from '@vendure/core';
 import { createTestEnvironment } from '@vendure/testing';
 import fs from 'fs-extra';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/auth.e2e-spec.ts

@@ -4,6 +4,7 @@ import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from
 import { DocumentNode } from 'graphql';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/authentication-strategy.e2e-spec.ts

@@ -5,6 +5,7 @@ import { mergeConfig, NativeAuthenticationStrategy } from '@vendure/core';
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/channel.e2e-spec.ts

@@ -8,6 +8,7 @@ import {
 } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 3 - 1
packages/core/e2e/collection.e2e-spec.ts

@@ -3,16 +3,18 @@ import { ROOT_COLLECTION_NAME } from '@vendure/common/lib/shared-constants';
 import {
     DefaultJobQueuePlugin,
     facetValueCollectionFilter,
+    productIdCollectionFilter,
+    variantIdCollectionFilter,
     variantNameCollectionFilter,
 } from '@vendure/core';
 import { createTestEnvironment, E2E_DEFAULT_CHANNEL_TOKEN } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
 import { pick } from '../../common/lib/pick';
-import { productIdCollectionFilter, variantIdCollectionFilter } from '../src/index';
 
 import { COLLECTION_FRAGMENT, FACET_VALUE_FRAGMENT } from './graphql/fragments';
 import * as Codegen from './graphql/generated-e2e-admin-types';

+ 1 - 0
packages/core/e2e/configurable-operation.e2e-spec.ts

@@ -8,6 +8,7 @@ import {
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/country.e2e-spec.ts

@@ -1,6 +1,7 @@
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 7 - 6
packages/core/e2e/custom-field-relations.e2e-spec.ts

@@ -20,6 +20,7 @@ import {
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -569,9 +570,9 @@ describe('Custom field relations', () => {
             });
         });
 
-        describe('Fulfillment entity', () => {
-            // Currently no GraphQL API to set customFields on fulfillments
-        });
+        // describe('Fulfillment entity', () => {
+        //     // Currently no GraphQL API to set customFields on fulfillments
+        // });
 
         describe('GlobalSettings entity', () => {
             it('admin updateGlobalSettings', async () => {
@@ -973,9 +974,9 @@ describe('Custom field relations', () => {
             });
         });
 
-        describe('User entity', () => {
-            // Currently no GraphQL API to set User custom fields
-        });
+        // describe('User entity', () => {
+        //     // Currently no GraphQL API to set User custom fields
+        // });
 
         describe('ShippingMethod entity', () => {
             let shippingMethodId: string;

+ 3 - 1
packages/core/e2e/custom-fields.e2e-spec.ts

@@ -4,6 +4,8 @@ import { createTestEnvironment } from '@vendure/testing';
 import { fail } from 'assert';
 import gql from 'graphql-tag';
 import path from 'path';
+import { vi } from 'vitest';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -15,7 +17,7 @@ fixPostgresTimezone();
 
 // tslint:disable:no-non-null-assertion
 
-const validateInjectorSpy = jest.fn();
+const validateInjectorSpy = vi.fn();
 
 const customConfig = mergeConfig(testConfig(), {
     dbConnectionOptions: {

+ 1 - 0
packages/core/e2e/custom-permissions.e2e-spec.ts

@@ -1,6 +1,7 @@
 import { mergeConfig } from '@vendure/core';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/customer-channel.e2e-spec.ts

@@ -1,6 +1,7 @@
 /* tslint:disable:no-non-null-assertion */
 import { createTestEnvironment, E2E_DEFAULT_CHANNEL_TOKEN } from '@vendure/testing';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/customer-group.e2e-spec.ts

@@ -1,6 +1,7 @@
 import { pick } from '@vendure/common/lib/pick';
 import { createTestEnvironment } from '@vendure/testing';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 4 - 2
packages/core/e2e/customer.e2e-spec.ts

@@ -12,6 +12,8 @@ import {
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { vi } from 'vitest';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -468,7 +470,7 @@ describe('Customer resolver', () => {
 
     describe('creation', () => {
         it('triggers verification event if no password supplied', async () => {
-            sendEmailFn = jest.fn();
+            sendEmailFn = vi.fn();
             const { createCustomer } = await adminClient.query<
                 Codegen.CreateCustomerMutation,
                 Codegen.CreateCustomerMutationVariables
@@ -488,7 +490,7 @@ describe('Customer resolver', () => {
         });
 
         it('creates a verified Customer', async () => {
-            sendEmailFn = jest.fn();
+            sendEmailFn = vi.fn();
             const { createCustomer } = await adminClient.query<
                 Codegen.CreateCustomerMutation,
                 Codegen.CreateCustomerMutationVariables

+ 1 - 0
packages/core/e2e/database-transactions.e2e-spec.ts

@@ -3,6 +3,7 @@ import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
 import { ReplaySubject } from 'rxjs';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/default-search-plugin-uuids.e2e-spec.ts

@@ -2,6 +2,7 @@
 import { DefaultJobQueuePlugin, DefaultSearchPlugin, mergeConfig, UuidIdStrategy } from '@vendure/core';
 import { createTestEnvironment, registerInitializer, SqljsInitializer } from '@vendure/testing';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 2 - 6
packages/core/e2e/default-search-plugin.e2e-spec.ts

@@ -2,7 +2,6 @@
 import { pick } from '@vendure/common/lib/pick';
 import {
     DefaultJobQueuePlugin,
-    DefaultLogger,
     DefaultSearchPlugin,
     facetValueCollectionFilter,
     mergeConfig,
@@ -16,10 +15,12 @@ import {
 } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
 
+import * as Codegen from './graphql/generated-e2e-admin-types';
 import {
     ChannelFragment,
     CurrencyCode,
@@ -28,7 +29,6 @@ import {
     SearchResultSortParameter,
     SortOrder,
 } from './graphql/generated-e2e-admin-types';
-import * as Codegen from './graphql/generated-e2e-admin-types';
 import {
     LogicalOperator,
     SearchProductsShopQuery,
@@ -58,10 +58,6 @@ import { awaitRunningJobs } from './utils/await-running-jobs';
 
 registerInitializer('sqljs', new SqljsInitializer(path.join(__dirname, '__data__'), 1000));
 
-// Some of these tests have many steps and can timeout
-// on the default of 5s.
-jest.setTimeout(10000);
-
 interface SearchProductShopQueryVariables extends SearchProductsShopQueryVariables {
     input: SearchProductsShopQueryVariables['input'] & {
         // This input field is dynamically added only when the `indexStockStatus` init option

+ 1 - 0
packages/core/e2e/draft-order.e2e-spec.ts

@@ -4,6 +4,7 @@ import { DefaultLogger, mergeConfig, orderPercentageDiscount } from '@vendure/co
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/entity-hydrator.e2e-spec.ts

@@ -3,6 +3,7 @@ import { mergeConfig, Order, Product, ProductVariant } from '@vendure/core';
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/entity-id-strategy.e2e-spec.ts

@@ -2,6 +2,7 @@
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/entity-prefix.e2e-spec.ts

@@ -1,6 +1,7 @@
 import { mergeConfig } from '@vendure/core';
 import { createTestEnvironment } from '@vendure/testing';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/entity-uuid-strategy.e2e-spec.ts

@@ -9,6 +9,7 @@ import { UuidIdStrategy } from '@vendure/core';
 import '@vendure/core/dist/index';
 import { createTestEnvironment } from '@vendure/testing';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/facet.e2e-spec.ts

@@ -2,6 +2,7 @@ import { pick } from '@vendure/common/lib/pick';
 import { createTestEnvironment, E2E_DEFAULT_CHANNEL_TOKEN } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 3 - 2
packages/core/e2e/fixtures/test-payment-methods.ts

@@ -1,4 +1,5 @@
 import { Payment, PaymentMethodHandler, TransactionalConnection } from '@vendure/core';
+import { vi } from 'vitest';
 
 import { LanguageCode } from '../graphql/generated-e2e-admin-types';
 
@@ -19,8 +20,8 @@ export const testSuccessfulPaymentMethod = new PaymentMethodHandler({
     }),
 });
 
-export const onTransitionSpy = jest.fn();
-export const onCancelPaymentSpy = jest.fn();
+export const onTransitionSpy = vi.fn();
+export const onCancelPaymentSpy = vi.fn();
 /**
  * A two-stage (authorize, capture) payment method, with no createRefund method.
  */

+ 2 - 1
packages/core/e2e/fixtures/test-plugins/issue-1636-1664/issue-1636-1664-plugin.ts

@@ -16,6 +16,7 @@ import {
 } from '@vendure/core';
 import gql from 'graphql-tag';
 import { Entity, JoinColumn, OneToOne } from 'typeorm';
+import { vi } from 'vitest';
 
 import { ProfileAsset } from './profile-asset.entity';
 import { Profile } from './profile.entity';
@@ -155,7 +156,7 @@ const profileType = gql`
 })
 // tslint:disable-next-line:class-name
 export class TestPlugin1636_1664 implements OnApplicationBootstrap {
-    static testResolverSpy = jest.fn();
+    static testResolverSpy = vi.fn();
 
     constructor(private connection: TransactionalConnection) {}
 

+ 3 - 2
packages/core/e2e/fixtures/test-plugins/transaction-test-plugin.ts

@@ -16,6 +16,7 @@ import {
 } from '@vendure/core';
 import gql from 'graphql-tag';
 import { ReplaySubject, Subscription } from 'rxjs';
+import { vi } from 'vitest';
 
 export class TestEvent extends VendureEvent {
     constructor(public ctx: RequestContext, public administrator: Administrator) {
@@ -304,8 +305,8 @@ class TestResolver {
 })
 export class TransactionTestPlugin implements OnApplicationBootstrap {
     private subscription: Subscription;
-    static callHandler = jest.fn();
-    static errorHandler = jest.fn();
+    static callHandler = vi.fn();
+    static errorHandler = vi.fn();
     static eventHandlerComplete$ = new ReplaySubject(1);
 
     constructor(private eventBus: EventBus, private connection: TransactionalConnection) {}

+ 7 - 5
packages/core/e2e/fulfillment-process.e2e-spec.ts

@@ -8,6 +8,8 @@ import {
 } from '@vendure/core';
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import path from 'path';
+import { vi } from 'vitest';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -25,11 +27,11 @@ import {
 import { ADD_ITEM_TO_ORDER } from './graphql/shop-definitions';
 import { addPaymentToOrder, proceedToArrangingPayment } from './utils/test-order-utils';
 
-const initSpy = jest.fn();
-const transitionStartSpy = jest.fn();
-const transitionEndSpy = jest.fn();
-const transitionEndSpy2 = jest.fn();
-const transitionErrorSpy = jest.fn();
+const initSpy = vi.fn();
+const transitionStartSpy = vi.fn();
+const transitionEndSpy = vi.fn();
+const transitionEndSpy2 = vi.fn();
+const transitionErrorSpy = vi.fn();
 
 describe('Fulfillment process', () => {
     const fulfillmentGuard: ErrorResultGuard<FulfillmentFragment> = createErrorResultGuard(

+ 1 - 0
packages/core/e2e/global-settings.e2e-spec.ts

@@ -1,6 +1,7 @@
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/import.e2e-spec.ts

@@ -5,6 +5,7 @@ import * as fs from 'fs';
 import gql from 'graphql-tag';
 import http from 'http';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/job-queue.e2e-spec.ts

@@ -2,6 +2,7 @@ import { DefaultJobQueuePlugin, mergeConfig } from '@vendure/core';
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 6 - 4
packages/core/e2e/lifecycle.e2e-spec.ts

@@ -8,14 +8,16 @@ import {
 } from '@vendure/core';
 import { createTestEnvironment } from '@vendure/testing';
 import path from 'path';
+import { vi } from 'vitest';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
 
-const strategyInitSpy = jest.fn();
-const strategyDestroySpy = jest.fn();
-const codInitSpy = jest.fn();
-const codDestroySpy = jest.fn();
+const strategyInitSpy = vi.fn();
+const strategyDestroySpy = vi.fn();
+const codInitSpy = vi.fn();
+const codDestroySpy = vi.fn();
 
 class TestIdStrategy extends AutoIncrementIdStrategy {
     async init(injector: Injector) {

+ 1 - 0
packages/core/e2e/list-query-builder.e2e-spec.ts

@@ -3,6 +3,7 @@ import { mergeConfig } from '@vendure/core';
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/localization.e2e-spec.ts

@@ -2,6 +2,7 @@ import { pick } from '@vendure/common/lib/pick';
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 2 - 2
packages/core/e2e/money-strategy.e2e-spec.ts

@@ -1,11 +1,11 @@
-import { CompatibilityMoneyStrategy, DefaultMoneyStrategy, mergeConfig } from '@vendure/core';
+import { DefaultMoneyStrategy, Logger, mergeConfig, MoneyStrategy } from '@vendure/core';
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import path from 'path';
 import { ColumnOptions } from 'typeorm';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
-import { Logger, MoneyStrategy } from '../src/index';
 
 import * as Codegen from './graphql/generated-e2e-admin-types';
 import { SortOrder } from './graphql/generated-e2e-admin-types';

+ 3 - 1
packages/core/e2e/order-changed-price-handling.e2e-spec.ts

@@ -8,6 +8,8 @@ import {
 } from '@vendure/core';
 import { createTestEnvironment } from '@vendure/testing';
 import path from 'path';
+import { vi } from 'vitest';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -18,7 +20,7 @@ import { UPDATE_PRODUCT_VARIANTS } from './graphql/shared-definitions';
 import { ADD_ITEM_TO_ORDER, ADJUST_ITEM_QUANTITY, GET_ACTIVE_ORDER } from './graphql/shop-definitions';
 
 class TestChangedPriceStrategy implements ChangedPriceHandlingStrategy {
-    static spy = jest.fn();
+    static spy = vi.fn();
     static useLatestPrice = true;
 
     handlePriceChange(

+ 1 - 0
packages/core/e2e/order-channel.e2e-spec.ts

@@ -6,6 +6,7 @@ import {
     ErrorResultGuard,
 } from '@vendure/testing';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 3 - 1
packages/core/e2e/order-fulfillment.e2e-spec.ts

@@ -9,6 +9,8 @@ import {
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { vi } from 'vitest';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -31,7 +33,7 @@ import { addPaymentToOrder, proceedToArrangingPayment } from './utils/test-order
 
 const badTrackingCode = 'bad-code';
 const transitionErrorMessage = 'Some error message';
-const transitionSpy = jest.fn();
+const transitionSpy = vi.fn();
 const testFulfillmentHandler = new FulfillmentHandler({
     code: 'test-fulfillment-handler',
     description: [{ languageCode: LanguageCode.en, value: 'Test fulfillment handler' }],

+ 1 - 0
packages/core/e2e/order-item-price-calculation-strategy.e2e-spec.ts

@@ -2,6 +2,7 @@ import { DefaultSearchPlugin, JobQueueService, mergeConfig } from '@vendure/core
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/order-merge.e2e-spec.ts

@@ -13,6 +13,7 @@ import {
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/order-modification.e2e-spec.ts

@@ -15,6 +15,7 @@ import {
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 7 - 5
packages/core/e2e/order-process.e2e-spec.ts

@@ -8,6 +8,8 @@ import {
 } from '@vendure/core';
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import path from 'path';
+import { vi } from 'vitest';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -37,11 +39,11 @@ import {
 
 type TestOrderState = OrderState | 'ValidatingCustomer';
 
-const initSpy = jest.fn();
-const transitionStartSpy = jest.fn();
-const transitionEndSpy = jest.fn();
-const transitionEndSpy2 = jest.fn();
-const transitionErrorSpy = jest.fn();
+const initSpy = vi.fn();
+const transitionStartSpy = vi.fn();
+const transitionEndSpy = vi.fn();
+const transitionEndSpy2 = vi.fn();
+const transitionErrorSpy = vi.fn();
 
 describe('Order process', () => {
     const VALIDATION_ERROR_MESSAGE = 'Customer must have a company email address';

+ 1 - 0
packages/core/e2e/order-promotion.e2e-spec.ts

@@ -22,6 +22,7 @@ import {
 } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/order-taxes.e2e-spec.ts

@@ -12,6 +12,7 @@ import {
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 2 - 1
packages/core/e2e/order.e2e-spec.ts

@@ -15,6 +15,7 @@ import {
 } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -1739,7 +1740,7 @@ describe('Orders resolver', () => {
         });
 
         // TODO: I think we should remove this restriction
-        xit('returns error result if attempting to refund the same item more than once', async () => {
+        it.skip('returns error result if attempting to refund the same item more than once', async () => {
             const { order } = await adminClient.query<Codegen.GetOrderQuery, Codegen.GetOrderQueryVariables>(
                 GET_ORDER,
                 {

+ 1 - 0
packages/core/e2e/parallel-transactions.e2e-spec.ts

@@ -1,5 +1,6 @@
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 3 - 1
packages/core/e2e/payment-method.e2e-spec.ts

@@ -13,6 +13,8 @@ import {
 } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { vi } from 'vitest';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -25,7 +27,7 @@ import { CREATE_CHANNEL } from './graphql/shared-definitions';
 import { ADD_ITEM_TO_ORDER, ADD_PAYMENT, GET_ELIGIBLE_PAYMENT_METHODS } from './graphql/shop-definitions';
 import { proceedToArrangingPayment } from './utils/test-order-utils';
 
-const checkerSpy = jest.fn();
+const checkerSpy = vi.fn();
 
 const minPriceChecker = new PaymentMethodEligibilityChecker({
     code: 'min-price-checker',

+ 7 - 5
packages/core/e2e/payment-process.e2e-spec.ts

@@ -16,6 +16,8 @@ import {
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { vi } from 'vitest';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -32,11 +34,11 @@ import {
 import { ADD_ITEM_TO_ORDER, ADD_PAYMENT, GET_ACTIVE_ORDER } from './graphql/shop-definitions';
 import { proceedToArrangingPayment } from './utils/test-order-utils';
 
-const initSpy = jest.fn();
-const transitionStartSpy = jest.fn();
-const transitionEndSpy = jest.fn();
-const transitionErrorSpy = jest.fn();
-const settlePaymentSpy = jest.fn();
+const initSpy = vi.fn();
+const transitionStartSpy = vi.fn();
+const transitionEndSpy = vi.fn();
+const transitionErrorSpy = vi.fn();
+const settlePaymentSpy = vi.fn();
 
 describe('Payment process', () => {
     let orderId: string;

+ 3 - 1
packages/core/e2e/plugin.e2e-spec.ts

@@ -3,6 +3,8 @@ import { ConfigService } from '@vendure/core';
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
+import { vi } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -16,7 +18,7 @@ import { TestPluginWithProvider } from './fixtures/test-plugins/with-provider';
 import { TestRestPlugin } from './fixtures/test-plugins/with-rest-controller';
 
 describe('Plugins', () => {
-    const onConstructorFn = jest.fn();
+    const onConstructorFn = vi.fn();
     const activeConfig = testConfig();
     const { server, adminClient, shopClient } = createTestEnvironment({
         ...activeConfig,

+ 1 - 0
packages/core/e2e/populate.e2e-spec.ts

@@ -3,6 +3,7 @@ import { DefaultLogger, User } from '@vendure/core';
 import { populate } from '@vendure/core/cli';
 import { createTestEnvironment, E2E_DEFAULT_CHANNEL_TOKEN } from '@vendure/testing';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/product-channel.e2e-spec.ts

@@ -1,6 +1,7 @@
 /* tslint:disable:no-non-null-assertion */
 import { createTestEnvironment, E2E_DEFAULT_CHANNEL_TOKEN } from '@vendure/testing';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/product-option.e2e-spec.ts

@@ -1,6 +1,7 @@
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/product.e2e-spec.ts

@@ -4,6 +4,7 @@ import { notNullOrUndefined } from '@vendure/common/lib/shared-utils';
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/promotion.e2e-spec.ts

@@ -8,6 +8,7 @@ import {
 } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/relations-decorator.e2e-spec.ts

@@ -2,6 +2,7 @@ import { mergeConfig, Zone } from '@vendure/core';
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 102 - 82
packages/core/e2e/role.e2e-spec.ts

@@ -8,6 +8,7 @@ import {
 import { createTestEnvironment, E2E_DEFAULT_CHANNEL_TOKEN } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -15,7 +16,14 @@ import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-conf
 import { ROLE_FRAGMENT } from './graphql/fragments';
 import * as Codegen from './graphql/generated-e2e-admin-types';
 import { CurrencyCode, DeletionResult, LanguageCode, Permission } from './graphql/generated-e2e-admin-types';
-import { CREATE_ADMINISTRATOR, CREATE_CHANNEL, CREATE_ROLE, GET_CHANNELS, UPDATE_ADMINISTRATOR, UPDATE_ROLE } from './graphql/shared-definitions';
+import {
+    CREATE_ADMINISTRATOR,
+    CREATE_CHANNEL,
+    CREATE_ROLE,
+    GET_CHANNELS,
+    UPDATE_ADMINISTRATOR,
+    UPDATE_ROLE,
+} from './graphql/shared-definitions';
 import { assertThrowsWithMessage } from './utils/assert-throws-with-message';
 import { sortById } from './utils/test-order-utils';
 
@@ -453,22 +461,22 @@ describe('Role resolver', () => {
             secondChannel = channels.find(c => c.token !== E2E_DEFAULT_CHANNEL_TOKEN)!;
             await adminClient.setChannelToken(E2E_DEFAULT_CHANNEL_TOKEN);
             await adminClient.asSuperAdmin();
-            const { createRole } = await adminClient.query<Codegen.CreateRoleMutation, Codegen.CreateRoleMutationVariables>(
-                CREATE_ROLE,
-                {
-                    input: {
-                        code: 'second-channel-admin-manager',
-                        description: '',
-                        channelIds: [secondChannel.id],
-                        permissions: [
-                            Permission.CreateAdministrator,
-                            Permission.ReadAdministrator,
-                            Permission.UpdateAdministrator,
-                            Permission.DeleteAdministrator,
-                        ],
-                    },
+            const { createRole } = await adminClient.query<
+                Codegen.CreateRoleMutation,
+                Codegen.CreateRoleMutationVariables
+            >(CREATE_ROLE, {
+                input: {
+                    code: 'second-channel-admin-manager',
+                    description: '',
+                    channelIds: [secondChannel.id],
+                    permissions: [
+                        Permission.CreateAdministrator,
+                        Permission.ReadAdministrator,
+                        Permission.UpdateAdministrator,
+                        Permission.DeleteAdministrator,
+                    ],
                 },
-            );
+            });
 
             const { createAdministrator } = await adminClient.query<
                 Codegen.CreateAdministratorMutation,
@@ -505,14 +513,17 @@ describe('Role resolver', () => {
         it(
             'limited admin cannot create Role with SuperAdmin permission',
             assertThrowsWithMessage(async () => {
-                await adminClient.query<Codegen.CreateRoleMutation, Codegen.CreateRoleMutationVariables>(CREATE_ROLE, {
-                    input: {
-                        code: 'evil-superadmin',
-                        description: '',
-                        channelIds: [secondChannel.id],
-                        permissions: [Permission.SuperAdmin],
+                await adminClient.query<Codegen.CreateRoleMutation, Codegen.CreateRoleMutationVariables>(
+                    CREATE_ROLE,
+                    {
+                        input: {
+                            code: 'evil-superadmin',
+                            description: '',
+                            channelIds: [secondChannel.id],
+                            permissions: [Permission.SuperAdmin],
+                        },
                     },
-                });
+                );
             }, 'The permission "SuperAdmin" may not be assigned'),
         );
 
@@ -520,79 +531,85 @@ describe('Role resolver', () => {
             'limited admin cannot create Administrator with SuperAdmin role',
             assertThrowsWithMessage(async () => {
                 const superAdminRole = defaultRoles.find(r => r.code === SUPER_ADMIN_ROLE_CODE)!;
-                await adminClient.query<Codegen.CreateAdministratorMutation, Codegen.CreateAdministratorMutationVariables>(
-                    CREATE_ADMINISTRATOR,
-                    {
-                        input: {
-                            firstName: 'Dr',
-                            lastName: 'Evil',
-                            emailAddress: 'drevil@test.com',
-                            roleIds: [superAdminRole.id],
-                            password: 'test',
-                        },
+                await adminClient.query<
+                    Codegen.CreateAdministratorMutation,
+                    Codegen.CreateAdministratorMutationVariables
+                >(CREATE_ADMINISTRATOR, {
+                    input: {
+                        firstName: 'Dr',
+                        lastName: 'Evil',
+                        emailAddress: 'drevil@test.com',
+                        roleIds: [superAdminRole.id],
+                        password: 'test',
                     },
-                );
+                });
             }, 'Active user does not have sufficient permissions'),
         );
 
         it(
             'limited admin cannot create Role with permissions it itself does not have',
             assertThrowsWithMessage(async () => {
-                await adminClient.query<Codegen.CreateRoleMutation, Codegen.CreateRoleMutationVariables>(CREATE_ROLE, {
-                    input: {
-                        code: 'evil-order-manager',
-                        description: '',
-                        channelIds: [secondChannel.id],
-                        permissions: [Permission.ReadOrder],
+                await adminClient.query<Codegen.CreateRoleMutation, Codegen.CreateRoleMutationVariables>(
+                    CREATE_ROLE,
+                    {
+                        input: {
+                            code: 'evil-order-manager',
+                            description: '',
+                            channelIds: [secondChannel.id],
+                            permissions: [Permission.ReadOrder],
+                        },
                     },
-                });
+                );
             }, 'Active user does not have sufficient permissions'),
         );
 
         it(
             'limited admin cannot create Role on channel it does not have permissions on',
             assertThrowsWithMessage(async () => {
-                await adminClient.query<Codegen.CreateRoleMutation, Codegen.CreateRoleMutationVariables>(CREATE_ROLE, {
-                    input: {
-                        code: 'evil-order-manager',
-                        description: '',
-                        channelIds: [defaultChannel.id],
-                        permissions: [Permission.CreateAdministrator],
+                await adminClient.query<Codegen.CreateRoleMutation, Codegen.CreateRoleMutationVariables>(
+                    CREATE_ROLE,
+                    {
+                        input: {
+                            code: 'evil-order-manager',
+                            description: '',
+                            channelIds: [defaultChannel.id],
+                            permissions: [Permission.CreateAdministrator],
+                        },
                     },
-                });
+                );
             }, 'You are not currently authorized to perform this action'),
         );
 
         it(
             'limited admin cannot create Administrator with a Role with greater permissions than they themselves have',
             assertThrowsWithMessage(async () => {
-                await adminClient.query<Codegen.CreateAdministratorMutation, Codegen.CreateAdministratorMutationVariables>(
-                    CREATE_ADMINISTRATOR,
-                    {
-                        input: {
-                            firstName: 'Dr',
-                            lastName: 'Evil',
-                            emailAddress: 'drevil@test.com',
-                            roleIds: [orderReaderRole.id],
-                            password: 'test',
-                        },
+                await adminClient.query<
+                    Codegen.CreateAdministratorMutation,
+                    Codegen.CreateAdministratorMutationVariables
+                >(CREATE_ADMINISTRATOR, {
+                    input: {
+                        firstName: 'Dr',
+                        lastName: 'Evil',
+                        emailAddress: 'drevil@test.com',
+                        roleIds: [orderReaderRole.id],
+                        password: 'test',
                     },
-                );
+                });
             }, 'Active user does not have sufficient permissions'),
         );
 
         it('limited admin can create Role with permissions it itself has', async () => {
-            const { createRole } = await adminClient.query<Codegen.CreateRoleMutation, Codegen.CreateRoleMutationVariables>(
-                CREATE_ROLE,
-                {
-                    input: {
-                        code: 'good-admin-creator',
-                        description: '',
-                        channelIds: [secondChannel.id],
-                        permissions: [Permission.CreateAdministrator],
-                    },
+            const { createRole } = await adminClient.query<
+                Codegen.CreateRoleMutation,
+                Codegen.CreateRoleMutationVariables
+            >(CREATE_ROLE, {
+                input: {
+                    code: 'good-admin-creator',
+                    description: '',
+                    channelIds: [secondChannel.id],
+                    permissions: [Permission.CreateAdministrator],
                 },
-            );
+            });
 
             expect(createRole.code).toBe('good-admin-creator');
             adminCreatorRole = createRole;
@@ -619,27 +636,30 @@ describe('Role resolver', () => {
         it(
             'limited admin cannot update Role with permissions it itself lacks',
             assertThrowsWithMessage(async () => {
-                await adminClient.query<Codegen.UpdateRoleMutation, Codegen.UpdateRoleMutationVariables>(UPDATE_ROLE, {
-                    input: {
-                        id: adminCreatorRole.id,
-                        permissions: [Permission.ReadOrder],
+                await adminClient.query<Codegen.UpdateRoleMutation, Codegen.UpdateRoleMutationVariables>(
+                    UPDATE_ROLE,
+                    {
+                        input: {
+                            id: adminCreatorRole.id,
+                            permissions: [Permission.ReadOrder],
+                        },
                     },
-                });
+                );
             }, 'Active user does not have sufficient permissions'),
         );
 
         it(
             'limited admin cannot update Administrator with Role containing permissions it itself lacks',
             assertThrowsWithMessage(async () => {
-                await adminClient.query<Codegen.UpdateAdministratorMutation, Codegen.UpdateAdministratorMutationVariables>(
-                    UPDATE_ADMINISTRATOR,
-                    {
-                        input: {
-                            id: adminCreatorAdministrator.id,
-                            roleIds: [adminCreatorRole.id, orderReaderRole.id],
-                        },
+                await adminClient.query<
+                    Codegen.UpdateAdministratorMutation,
+                    Codegen.UpdateAdministratorMutationVariables
+                >(UPDATE_ADMINISTRATOR, {
+                    input: {
+                        id: adminCreatorAdministrator.id,
+                        roleIds: [adminCreatorRole.id, orderReaderRole.id],
                     },
-                );
+                });
             }, 'Active user does not have sufficient permissions'),
         );
     });

+ 6 - 4
packages/core/e2e/session-management.e2e-spec.ts

@@ -3,6 +3,8 @@ import { CachedSession, mergeConfig, SessionCacheStrategy } from '@vendure/core'
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
+import { vi } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -16,10 +18,10 @@ import {
 import { ATTEMPT_LOGIN, ME } from './graphql/shared-definitions';
 
 const testSessionCache = new Map<string, CachedSession>();
-const getSpy = jest.fn();
-const setSpy = jest.fn();
-const clearSpy = jest.fn();
-const deleteSpy = jest.fn();
+const getSpy = vi.fn();
+const setSpy = vi.fn();
+const clearSpy = vi.fn();
+const deleteSpy = vi.fn();
 
 class TestingSessionCacheStrategy implements SessionCacheStrategy {
     clear() {

+ 5 - 3
packages/core/e2e/shipping-method-eligibility.e2e-spec.ts

@@ -7,6 +7,8 @@ import {
 } from '@vendure/core';
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import path from 'path';
+import { vi } from 'vitest';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -25,7 +27,7 @@ import {
     SET_SHIPPING_METHOD,
 } from './graphql/shop-definitions';
 
-const check1Spy = jest.fn();
+const check1Spy = vi.fn();
 const checker1 = new ShippingEligibilityChecker({
     code: 'checker1',
     description: [],
@@ -36,7 +38,7 @@ const checker1 = new ShippingEligibilityChecker({
     },
 });
 
-const check2Spy = jest.fn();
+const check2Spy = vi.fn();
 const checker2 = new ShippingEligibilityChecker({
     code: 'checker2',
     description: [],
@@ -47,7 +49,7 @@ const checker2 = new ShippingEligibilityChecker({
     },
 });
 
-const check3Spy = jest.fn();
+const check3Spy = vi.fn();
 const checker3 = new ShippingEligibilityChecker({
     code: 'checker3',
     description: [],

+ 1 - 0
packages/core/e2e/shipping-method.e2e-spec.ts

@@ -7,6 +7,7 @@ import {
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 14 - 12
packages/core/e2e/shop-auth.e2e-spec.ts

@@ -18,6 +18,8 @@ import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from
 import { DocumentNode } from 'graphql';
 import gql from 'graphql-tag';
 import path from 'path';
+import { Mock, vi } from 'vitest';
+import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
@@ -45,7 +47,7 @@ import {
     VERIFY_EMAIL,
 } from './graphql/shop-definitions';
 
-let sendEmailFn: jest.Mock;
+let sendEmailFn: Mock;
 
 /**
  * This mock plugin simulates an EmailPlugin which would send emails
@@ -127,7 +129,7 @@ describe('Shop auth & accounts', () => {
         let newCustomerId: string;
 
         beforeEach(() => {
-            sendEmailFn = jest.fn();
+            sendEmailFn = vi.fn();
         });
 
         it('does not return error result on email address conflict', async () => {
@@ -500,7 +502,7 @@ describe('Shop auth & accounts', () => {
         });
 
         beforeEach(() => {
-            sendEmailFn = jest.fn();
+            sendEmailFn = vi.fn();
         });
 
         it('requestPasswordReset silently fails with invalid identifier', async () => {
@@ -616,7 +618,7 @@ describe('Shop auth & accounts', () => {
         let newCustomerId: string;
 
         beforeEach(() => {
-            sendEmailFn = jest.fn();
+            sendEmailFn = vi.fn();
         });
 
         it('register a new account without password', async () => {
@@ -627,10 +629,10 @@ describe('Shop auth & accounts', () => {
                 phoneNumber: '123456',
                 emailAddress,
             };
-            const { registerCustomerAccount } = await shopClient.query<Codegen.RegisterMutation, Codegen.RegisterMutationVariables>(
-                REGISTER_ACCOUNT,
-                { input },
-            );
+            const { registerCustomerAccount } = await shopClient.query<
+                Codegen.RegisterMutation,
+                Codegen.RegisterMutationVariables
+            >(REGISTER_ACCOUNT, { input });
             successErrorGuard.assertSuccess(registerCustomerAccount);
             verificationToken = await verificationTokenPromise;
 
@@ -710,7 +712,7 @@ describe('Shop auth & accounts', () => {
         });
 
         beforeEach(() => {
-            sendEmailFn = jest.fn();
+            sendEmailFn = vi.fn();
         });
 
         it('throws if not logged in', async () => {
@@ -962,7 +964,7 @@ describe('Expiring tokens', () => {
     }, TEST_SETUP_TIMEOUT_MS);
 
     beforeEach(() => {
-        sendEmailFn = jest.fn();
+        sendEmailFn = vi.fn();
     });
 
     afterAll(async () => {
@@ -1067,7 +1069,7 @@ describe('Registration without email verification', () => {
     }, TEST_SETUP_TIMEOUT_MS);
 
     beforeEach(() => {
-        sendEmailFn = jest.fn();
+        sendEmailFn = vi.fn();
     });
 
     afterAll(async () => {
@@ -1156,7 +1158,7 @@ describe('Updating email address without email verification', () => {
     }, TEST_SETUP_TIMEOUT_MS);
 
     beforeEach(() => {
-        sendEmailFn = jest.fn();
+        sendEmailFn = vi.fn();
     });
 
     afterAll(async () => {

+ 1 - 0
packages/core/e2e/shop-catalog.e2e-spec.ts

@@ -3,6 +3,7 @@ import { facetValueCollectionFilter, JobQueueService } from '@vendure/core';
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/shop-customer.e2e-spec.ts

@@ -3,6 +3,7 @@ import { pick } from '@vendure/common/lib/pick';
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 4 - 3
packages/core/e2e/shop-order.e2e-spec.ts

@@ -4,15 +4,17 @@ import {
     Asset,
     defaultShippingCalculator,
     defaultShippingEligibilityChecker,
+    manualFulfillmentHandler,
     mergeConfig,
 } from '@vendure/core';
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { vi } from 'vitest';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
-import { manualFulfillmentHandler } from '../src/index';
 
 import {
     testErrorPaymentMethod,
@@ -106,7 +108,6 @@ describe('Shop orders', () => {
         | CodegenShop.UpdatedOrderFragment
         | CodegenShop.TestOrderFragmentFragment
         | CodegenShop.TestOrderWithPaymentsFragment
-        | CodegenShop.CanceledOrderFragment
         | CodegenShop.ActiveOrderCustomerFragment;
     const orderResultGuard: ErrorResultGuard<OrderSuccessResult> = createErrorResultGuard(
         input => !!input.lines,
@@ -1544,7 +1545,7 @@ describe('Shop orders', () => {
                 beforeAll(() => {
                     // mock Date.now: add 3 hours
                     const nowIn3H = Date.now() + 3 * 3600 * 1000;
-                    dateNowMock = jest.spyOn(global.Date, 'now').mockImplementation(() => nowIn3H);
+                    dateNowMock = vi.spyOn(global.Date, 'now').mockImplementation(() => nowIn3H);
                 });
 
                 it('still works when authenticated as owner', async () => {

+ 1 - 0
packages/core/e2e/stock-control-multi-location.e2e-spec.ts

@@ -3,6 +3,7 @@ import { manualFulfillmentHandler, mergeConfig } from '@vendure/core';
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/stock-control.e2e-spec.ts

@@ -11,6 +11,7 @@ import {
 import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/tag.e2e-spec.ts

@@ -1,5 +1,6 @@
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/tax-category.e2e-spec.ts

@@ -1,6 +1,7 @@
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/tax-rate.e2e-spec.ts

@@ -3,6 +3,7 @@ import { pick } from '@vendure/common/lib/pick';
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/translations.e2e-spec.ts

@@ -2,6 +2,7 @@ import { LanguageCode, mergeConfig } from '@vendure/core';
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 1 - 0
packages/core/e2e/utils/assert-throws-with-message.ts

@@ -1,4 +1,5 @@
 import { fail } from 'assert';
+import { expect } from 'vitest';
 
 /**
  * Helper method for creating tests which assert a given error message when the operation is attempted.

+ 1 - 0
packages/core/e2e/utils/await-running-jobs.ts

@@ -1,4 +1,5 @@
 import { SimpleGraphQLClient } from '@vendure/testing';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { GetRunningJobs, JobState } from '../graphql/generated-e2e-admin-types';
 import { GET_RUNNING_JOBS } from '../graphql/shared-definitions';

+ 1 - 0
packages/core/e2e/utils/test-order-utils.ts

@@ -2,6 +2,7 @@
 import { ID } from '@vendure/common/lib/shared-types';
 import { PaymentMethodHandler } from '@vendure/core';
 import { SimpleGraphQLClient } from '@vendure/testing';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import * as CodegenShop from '../graphql/generated-e2e-shop-types';
 import { TestOrderFragmentFragment } from '../graphql/generated-e2e-shop-types';

+ 1 - 0
packages/core/e2e/zone.e2e-spec.ts

@@ -1,6 +1,7 @@
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import path from 'path';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';

+ 5 - 4
packages/core/package.json

@@ -25,7 +25,8 @@
     "watch": "concurrently yarn:tsc:watch yarn:gulp:watch",
     "lint": "tslint --fix --project ./",
     "test": "jest --config ./jest.config.js",
-    "e2e": "jest --config ../../e2e-common/jest-config.js --package=core",
+    "e2e": "node --experimental-vm-modules ../../node_modules/jest/bin/jest.js --config ../../e2e-common/jest-config.js --package=core",
+    "e2e:vitest": "vitest --config ../../e2e-common/vitest.config.ts",
     "ci": "yarn build"
   },
   "publishConfig": {
@@ -96,10 +97,10 @@
     "better-sqlite3": "^7.1.1",
     "gulp": "^4.0.2",
     "mysql": "^2.18.1",
-    "pg": "^8.4.0",
+    "pg": "^8.10.0",
     "rimraf": "^3.0.2",
-    "sql.js": "1.3.2",
-    "sqlite3": "^5.0.0",
+    "sql.js": "1.8.0",
+    "sqlite3": "^5.1.4",
     "typescript": "4.9.5"
   }
 }

+ 524 - 9
yarn.lock

@@ -1699,6 +1699,11 @@
     pump "^3.0.0"
     secure-json-parse "^2.1.0"
 
+"@esbuild/android-arm64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz#cf91e86df127aa3d141744edafcba0abdc577d23"
+  integrity sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==
+
 "@esbuild/android-arm64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.11.tgz#52c3e6cabc19c5e4c1c0c01cb58f0442338e1c14"
@@ -1709,6 +1714,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.8.tgz#b3d5b65a3b2e073a6c7ee36b1f3c30c8f000315b"
   integrity sha512-oa/N5j6v1svZQs7EIRPqR8f+Bf8g6HBDjD/xHC02radE/NjKHK7oQmtmLxPs1iVwYyvE+Kolo6lbpfEQ9xnhxQ==
 
+"@esbuild/android-arm@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.16.17.tgz#025b6246d3f68b7bbaa97069144fb5fb70f2fff2"
+  integrity sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==
+
 "@esbuild/android-arm@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.11.tgz#f3fc768235aecbeb840d0049fdf13cd28592105f"
@@ -1719,6 +1729,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.8.tgz#c41e496af541e175369d48164d0cf01a5f656cf6"
   integrity sha512-0/rb91GYKhrtbeglJXOhAv9RuYimgI8h623TplY2X+vA4EXnk3Zj1fXZreJ0J3OJJu1bwmb0W7g+2cT/d8/l/w==
 
+"@esbuild/android-x64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.16.17.tgz#c820e0fef982f99a85c4b8bfdd582835f04cd96e"
+  integrity sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==
+
 "@esbuild/android-x64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.11.tgz#443ed47771a7e917e4282469ba350d117473550c"
@@ -1729,6 +1744,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.8.tgz#080fa67c29be77f5a3ca5ee4cc78d5bf927e3a3b"
   integrity sha512-bTliMLqD7pTOoPg4zZkXqCDuzIUguEWLpeqkNfC41ODBHwoUgZ2w5JBeYimv4oP6TDVocoYmEhZrCLQTrH89bg==
 
+"@esbuild/darwin-arm64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz#edef4487af6b21afabba7be5132c26d22379b220"
+  integrity sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==
+
 "@esbuild/darwin-arm64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.11.tgz#0e8c78d94d5759a48521dbfd83189d2ed3499a16"
@@ -1739,6 +1759,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.8.tgz#053622bf9a82f43d5c075b7818e02618f7b4a397"
   integrity sha512-ghAbV3ia2zybEefXRRm7+lx8J/rnupZT0gp9CaGy/3iolEXkJ6LYRq4IpQVI9zR97ID80KJVoUlo3LSeA/sMAg==
 
+"@esbuild/darwin-x64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz#42829168730071c41ef0d028d8319eea0e2904b4"
+  integrity sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==
+
 "@esbuild/darwin-x64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.11.tgz#2405cfdf70eb961c7cf973463ca7263dc2004c88"
@@ -1749,6 +1774,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.8.tgz#8a1aadb358d537d8efad817bb1a5bff91b84734b"
   integrity sha512-n5WOpyvZ9TIdv2V1K3/iIkkJeKmUpKaCTdun9buhGRWfH//osmUjlv4Z5mmWdPWind/VGcVxTHtLfLCOohsOXw==
 
+"@esbuild/freebsd-arm64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz#1f4af488bfc7e9ced04207034d398e793b570a27"
+  integrity sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==
+
 "@esbuild/freebsd-arm64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.11.tgz#d5138e873e15f87bd4564c024dfa00ef37e623fd"
@@ -1759,6 +1789,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.8.tgz#e6738d0081ba0721a5c6c674e84c6e7fcea61989"
   integrity sha512-a/SATTaOhPIPFWvHZDoZYgxaZRVHn0/LX1fHLGfZ6C13JqFUZ3K6SMD6/HCtwOQ8HnsNaEeokdiDSFLuizqv5A==
 
+"@esbuild/freebsd-x64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz#636306f19e9bc981e06aa1d777302dad8fddaf72"
+  integrity sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==
+
 "@esbuild/freebsd-x64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.11.tgz#e850b58b8fabf8e9ef0e125af3c25229ad2d6c38"
@@ -1769,6 +1804,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.8.tgz#1855e562f2b730f4483f6e94086e9e2597feb4c3"
   integrity sha512-xpFJb08dfXr5+rZc4E+ooZmayBW6R3q59daCpKZ/cDU96/kvDM+vkYzNeTJCGd8rtO6fHWMq5Rcv/1cY6p6/0Q==
 
+"@esbuild/linux-arm64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz#a003f7ff237c501e095d4f3a09e58fc7b25a4aca"
+  integrity sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==
+
 "@esbuild/linux-arm64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.11.tgz#2bfb93d0809ec2357c12ebb27736b750c9ae0aa5"
@@ -1779,6 +1819,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.8.tgz#481da38952721a3fdb77c17a36ceaacc4270b5c5"
   integrity sha512-v3iwDQuDljLTxpsqQDl3fl/yihjPAyOguxuloON9kFHYwopeJEf1BkDXODzYyXEI19gisEsQlG1bM65YqKSIww==
 
+"@esbuild/linux-arm@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz#b591e6a59d9c4fe0eeadd4874b157ab78cf5f196"
+  integrity sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==
+
 "@esbuild/linux-arm@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.11.tgz#e56fb3b76828317a704f4a167c5bd790fe5314e7"
@@ -1789,6 +1834,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.8.tgz#18127072b270bb6321c6d11be20bfd30e0d6ad17"
   integrity sha512-6Ij8gfuGszcEwZpi5jQIJCVIACLS8Tz2chnEBfYjlmMzVsfqBP1iGmHQPp7JSnZg5xxK9tjCc+pJ2WtAmPRFVA==
 
+"@esbuild/linux-ia32@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz#24333a11027ef46a18f57019450a5188918e2a54"
+  integrity sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==
+
 "@esbuild/linux-ia32@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.11.tgz#59fa1c49b271793d14eb5effc757e8c0d0cb2cab"
@@ -1799,6 +1849,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.8.tgz#ee400af7b3bc69e8ca2e593ca35156ffb9abd54f"
   integrity sha512-8svILYKhE5XetuFk/B6raFYIyIqydQi+GngEXJgdPdI7OMKUbSd7uzR02wSY4kb53xBrClLkhH4Xs8P61Q2BaA==
 
+"@esbuild/linux-loong64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz#d5ad459d41ed42bbd4d005256b31882ec52227d8"
+  integrity sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==
+
 "@esbuild/linux-loong64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.11.tgz#89575bc189099c03a36daa54f3f481780c7fd502"
@@ -1809,6 +1864,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.8.tgz#8c509d8a454693d39824b83b3f66c400872fce82"
   integrity sha512-B6FyMeRJeV0NpyEOYlm5qtQfxbdlgmiGdD+QsipzKfFky0K5HW5Td6dyK3L3ypu1eY4kOmo7wW0o94SBqlqBSA==
 
+"@esbuild/linux-mips64el@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz#4e5967a665c38360b0a8205594377d4dcf9c3726"
+  integrity sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==
+
 "@esbuild/linux-mips64el@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.11.tgz#0e18ca039dc7e4645efd8edc1b10952933eb6b1b"
@@ -1819,6 +1879,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.8.tgz#f2b0d36e63fb26bc3f95b203b6a80638292101ca"
   integrity sha512-CCb67RKahNobjm/eeEqeD/oJfJlrWyw29fgiyB6vcgyq97YAf3gCOuP6qMShYSPXgnlZe/i4a8WFHBw6N8bYAA==
 
+"@esbuild/linux-ppc64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz#206443a02eb568f9fdf0b438fbd47d26e735afc8"
+  integrity sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==
+
 "@esbuild/linux-ppc64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.11.tgz#2d152cb3a253afb8c100a165ad132dc96f36cb11"
@@ -1829,6 +1894,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.8.tgz#1e628be003e036e90423716028cc884fe5ba25bd"
   integrity sha512-bytLJOi55y55+mGSdgwZ5qBm0K9WOCh0rx+vavVPx+gqLLhxtSFU0XbeYy/dsAAD6xECGEv4IQeFILaSS2auXw==
 
+"@esbuild/linux-riscv64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz#c351e433d009bf256e798ad048152c8d76da2fc9"
+  integrity sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==
+
 "@esbuild/linux-riscv64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.11.tgz#c6ac494a81221d53d65b33e665c7df1747952d3c"
@@ -1839,6 +1909,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.8.tgz#419a815cb4c3fb9f1b78ef5295f5b48b8bf6427a"
   integrity sha512-2YpRyQJmKVBEHSBLa8kBAtbhucaclb6ex4wchfY0Tj3Kg39kpjeJ9vhRU7x4mUpq8ISLXRXH1L0dBYjAeqzZAw==
 
+"@esbuild/linux-s390x@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz#661f271e5d59615b84b6801d1c2123ad13d9bd87"
+  integrity sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==
+
 "@esbuild/linux-s390x@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.11.tgz#4bad33894bc7415cea4be8fa90fe456226a424ad"
@@ -1849,6 +1924,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.8.tgz#291c49ae5c3d11d226352755c0835911fe1a9e5c"
   integrity sha512-QgbNY/V3IFXvNf11SS6exkpVcX0LJcob+0RWCgV9OiDAmVElnxciHIisoSix9uzYzScPmS6dJFbZULdSAEkQVw==
 
+"@esbuild/linux-x64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz#e4ba18e8b149a89c982351443a377c723762b85f"
+  integrity sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==
+
 "@esbuild/linux-x64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.11.tgz#903fda743459f530a16a6c6ee8d2c0f6c1a12fc7"
@@ -1859,6 +1939,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.8.tgz#03199d91c76faf80bd54104f5cbf0a489bc39f6a"
   integrity sha512-mM/9S0SbAFDBc4OPoyP6SEOo5324LpUxdpeIUUSrSTOfhHU9hEfqRngmKgqILqwx/0DVJBzeNW7HmLEWp9vcOA==
 
+"@esbuild/netbsd-x64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz#7d4f4041e30c5c07dd24ffa295c73f06038ec775"
+  integrity sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==
+
 "@esbuild/netbsd-x64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.11.tgz#b589239fe7d9b16ee03c5e191f3f5b640f1518a1"
@@ -1869,6 +1954,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.8.tgz#b436d767e1b21852f9ed212e2bb57f77203b0ae2"
   integrity sha512-eKUYcWaWTaYr9zbj8GertdVtlt1DTS1gNBWov+iQfWuWyuu59YN6gSEJvFzC5ESJ4kMcKR0uqWThKUn5o8We6Q==
 
+"@esbuild/openbsd-x64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz#970fa7f8470681f3e6b1db0cc421a4af8060ec35"
+  integrity sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==
+
 "@esbuild/openbsd-x64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.11.tgz#b355019754116bef39ec688f8fd2fe6471b9779b"
@@ -1879,6 +1969,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.8.tgz#d1481d8539e21d4729cd04a0450a26c2c8789e89"
   integrity sha512-Vc9J4dXOboDyMXKD0eCeW0SIeEzr8K9oTHJU+Ci1mZc5njPfhKAqkRt3B/fUNU7dP+mRyralPu8QUkiaQn7iIg==
 
+"@esbuild/sunos-x64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz#abc60e7c4abf8b89fb7a4fe69a1484132238022c"
+  integrity sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==
+
 "@esbuild/sunos-x64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.11.tgz#2ea47fb592e68406e5025a7696dc714fc6a115dc"
@@ -1889,6 +1984,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.8.tgz#2cfb8126e079b2c00fd1bf095541e9f5c47877e4"
   integrity sha512-0xvOTNuPXI7ft1LYUgiaXtpCEjp90RuBBYovdd2lqAFxje4sEucurg30M1WIm03+3jxByd3mfo+VUmPtRSVuOw==
 
+"@esbuild/win32-arm64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz#7b0ff9e8c3265537a7a7b1fd9a24e7bd39fcd87a"
+  integrity sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==
+
 "@esbuild/win32-arm64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.11.tgz#47e6fdab17c4c52e6e0d606dd9cb843b29826325"
@@ -1899,6 +1999,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.8.tgz#7c6ecfd097ca23b82119753bf7072bbaefe51e3a"
   integrity sha512-G0JQwUI5WdEFEnYNKzklxtBheCPkuDdu1YrtRrjuQv30WsYbkkoixKxLLv8qhJmNI+ATEWquZe/N0d0rpr55Mg==
 
+"@esbuild/win32-ia32@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz#e90fe5267d71a7b7567afdc403dfd198c292eb09"
+  integrity sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==
+
 "@esbuild/win32-ia32@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.11.tgz#a97273aa3164c8d8f501899f55cc75a4a79599a3"
@@ -1909,6 +2014,11 @@
   resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.8.tgz#cffec63c3cb0ef8563a04df4e09fa71056171d00"
   integrity sha512-Fqy63515xl20OHGFykjJsMnoIWS+38fqfg88ClvPXyDbLtgXal2DTlhb1TfTX34qWi3u4I7Cq563QcHpqgLx8w==
 
+"@esbuild/win32-x64@0.16.17":
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz#c5a1a4bfe1b57f0c3e61b29883525c6da3e5c091"
+  integrity sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==
+
 "@esbuild/win32-x64@0.17.11":
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.11.tgz#9be796d93ae27b636da32d960899a4912bca27a1"
@@ -4156,6 +4266,72 @@
   resolved "https://registry.yarnpkg.com/@sqltools/formatter/-/formatter-1.2.5.tgz#3abc203c79b8c3e90fd6c156a0c62d5403520e12"
   integrity sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==
 
+"@swc/core-darwin-arm64@1.3.38":
+  version "1.3.38"
+  resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.38.tgz#1ce367373f39e7d67f8c03f8224b2085bf38d083"
+  integrity sha512-4ZTJJ/cR0EsXW5UxFCifZoGfzQ07a8s4ayt1nLvLQ5QoB1GTAf9zsACpvWG8e7cmCR0L76R5xt8uJuyr+noIXA==
+
+"@swc/core-darwin-x64@1.3.38":
+  version "1.3.38"
+  resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.38.tgz#6312528e5aa846b1e518aedc81d718b0f956a7c4"
+  integrity sha512-Kim727rNo4Dl8kk0CR8aJQe4zFFtsT1TZGlNrNMUgN1WC3CRX7dLZ6ZJi/VVcTG1cbHp5Fp3mUzwHsMxEh87Mg==
+
+"@swc/core-linux-arm-gnueabihf@1.3.38":
+  version "1.3.38"
+  resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.38.tgz#211b6994c5e04c8bc509091403bd9137ebee5d89"
+  integrity sha512-yaRdnPNU2enlJDRcIMvYVSyodY+Amhf5QuXdUbAj6rkDD6wUs/s9C6yPYrFDmoTltrG+nBv72mUZj+R46wVfSw==
+
+"@swc/core-linux-arm64-gnu@1.3.38":
+  version "1.3.38"
+  resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.38.tgz#88d12e7e0469b91b8847403c415f9f7afb8d94a6"
+  integrity sha512-iNY1HqKo/wBSu3QOGBUlZaLdBP/EHcwNjBAqIzpb8J64q2jEN02RizqVW0mDxyXktJ3lxr3g7VW9uqklMeXbjQ==
+
+"@swc/core-linux-arm64-musl@1.3.38":
+  version "1.3.38"
+  resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.38.tgz#e0ead57c88ece8d339c1626730d0e5985df4e8fb"
+  integrity sha512-LJCFgLZoPRkPCPmux+Q5ctgXRp6AsWhvWuY61bh5bIPBDlaG9pZk94DeHyvtiwT0syhTtXb2LieBOx6NqN3zeA==
+
+"@swc/core-linux-x64-gnu@1.3.38":
+  version "1.3.38"
+  resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.38.tgz#21fc6636eeab058d4f707f4d88e29970802737b8"
+  integrity sha512-hRQGRIWHmv2PvKQM/mMV45mVXckM2+xLB8TYLLgUG66mmtyGTUJPyxjnJkbI86WNGqo18k+lAuMG2mn6QmzYwQ==
+
+"@swc/core-linux-x64-musl@1.3.38":
+  version "1.3.38"
+  resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.38.tgz#0a8b53c14993bbdea0dca8c8ae1084c05dc77346"
+  integrity sha512-PTYSqtsIfPHLKDDNbueI5e0sc130vyHRiFOeeC6qqzA2FAiVvIxuvXHLr0soPvKAR1WyhtYmFB9QarcctemL2w==
+
+"@swc/core-win32-arm64-msvc@1.3.38":
+  version "1.3.38"
+  resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.38.tgz#affd14cf941f0e147aa0211456e08036685d042e"
+  integrity sha512-9lHfs5TPNs+QdkyZFhZledSmzBEbqml/J1rqPSb9Fy8zB6QlspixE6OLZ3nTlUOdoGWkcTTdrOn77Sd7YGf1AA==
+
+"@swc/core-win32-ia32-msvc@1.3.38":
+  version "1.3.38"
+  resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.38.tgz#cf807fd74ef9551994d959db562a07605788fddc"
+  integrity sha512-SbL6pfA2lqvDKnwTHwOfKWvfHAdcbAwJS4dBkFidr7BiPTgI5Uk8wAPcRb8mBECpmIa9yFo+N0cAFRvMnf+cNw==
+
+"@swc/core-win32-x64-msvc@1.3.38":
+  version "1.3.38"
+  resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.38.tgz#9b6a746cf90b77171d1348311a04c149d3b06ba7"
+  integrity sha512-UFveLrL6eGvViOD8OVqUQa6QoQwdqwRvLtL5elF304OT8eCPZa8BhuXnWk25X8UcOyns8gFcb8Fhp3oaLi/Rlw==
+
+"@swc/core@^1.3.38":
+  version "1.3.38"
+  resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.38.tgz#c3b3515e23f42cbea0590609ee07fd91193f3499"
+  integrity sha512-AiEVehRFws//AiiLx9DPDp1WDXt+yAoGD1kMYewhoF6QLdTz8AtYu6i8j/yAxk26L8xnegy0CDwcNnub9qenyQ==
+  optionalDependencies:
+    "@swc/core-darwin-arm64" "1.3.38"
+    "@swc/core-darwin-x64" "1.3.38"
+    "@swc/core-linux-arm-gnueabihf" "1.3.38"
+    "@swc/core-linux-arm64-gnu" "1.3.38"
+    "@swc/core-linux-arm64-musl" "1.3.38"
+    "@swc/core-linux-x64-gnu" "1.3.38"
+    "@swc/core-linux-x64-musl" "1.3.38"
+    "@swc/core-win32-arm64-msvc" "1.3.38"
+    "@swc/core-win32-ia32-msvc" "1.3.38"
+    "@swc/core-win32-x64-msvc" "1.3.38"
+
 "@tokenizer/token@^0.3.0":
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276"
@@ -4272,6 +4448,18 @@
   dependencies:
     "@types/node" "*"
 
+"@types/chai-subset@^1.3.3":
+  version "1.3.3"
+  resolved "https://registry.yarnpkg.com/@types/chai-subset/-/chai-subset-1.3.3.tgz#97893814e92abd2c534de422cb377e0e0bdaac94"
+  integrity sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==
+  dependencies:
+    "@types/chai" "*"
+
+"@types/chai@*", "@types/chai@^4.3.4":
+  version "4.3.4"
+  resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4"
+  integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==
+
 "@types/connect-history-api-fallback@^1.3.5":
   version "1.3.5"
   resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae"
@@ -4928,6 +5116,42 @@
     terminal-link "^3.0.0"
     yargs "^17.5.1"
 
+"@vitest/expect@0.29.2":
+  version "0.29.2"
+  resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-0.29.2.tgz#7503aabd72764612b0bc8258bafa3232ccb81586"
+  integrity sha512-wjrdHB2ANTch3XKRhjWZN0UueFocH0cQbi2tR5Jtq60Nb3YOSmakjdAvUa2JFBu/o8Vjhj5cYbcMXkZxn1NzmA==
+  dependencies:
+    "@vitest/spy" "0.29.2"
+    "@vitest/utils" "0.29.2"
+    chai "^4.3.7"
+
+"@vitest/runner@0.29.2":
+  version "0.29.2"
+  resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-0.29.2.tgz#bbc7b239758de4158392bb343e48ee5a4aa507e1"
+  integrity sha512-A1P65f5+6ru36AyHWORhuQBJrOOcmDuhzl5RsaMNFe2jEkoj0faEszQS4CtPU/LxUYVIazlUtZTY0OEZmyZBnA==
+  dependencies:
+    "@vitest/utils" "0.29.2"
+    p-limit "^4.0.0"
+    pathe "^1.1.0"
+
+"@vitest/spy@0.29.2":
+  version "0.29.2"
+  resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-0.29.2.tgz#4210d844fabd9a68a1d2932d6a26c051bd089021"
+  integrity sha512-Hc44ft5kaAytlGL2PyFwdAsufjbdOvHklwjNy/gy/saRbg9Kfkxfh+PklLm1H2Ib/p586RkQeNFKYuJInUssyw==
+  dependencies:
+    tinyspy "^1.0.2"
+
+"@vitest/utils@0.29.2":
+  version "0.29.2"
+  resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-0.29.2.tgz#8990794a6855de19b59da80413dc5a1e1991da4d"
+  integrity sha512-F14/Uc+vCdclStS2KEoXJlOLAEyqRhnw0gM27iXw9bMTcyKRPJrQ+rlC6XZ125GIPvvKYMPpVxNhiou6PsEeYQ==
+  dependencies:
+    cli-truncate "^3.1.0"
+    diff "^5.1.0"
+    loupe "^2.3.6"
+    picocolors "^1.0.0"
+    pretty-format "^27.5.1"
+
 "@webassemblyjs/ast@1.11.1":
   version "1.11.1"
   resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7"
@@ -5165,12 +5389,12 @@ acorn-import-assertions@^1.7.6:
   resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9"
   integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==
 
-acorn-walk@^8.1.1:
+acorn-walk@^8.1.1, acorn-walk@^8.2.0:
   version "8.2.0"
   resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
   integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
 
-acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1:
+acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2:
   version "8.8.2"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
   integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
@@ -5367,7 +5591,7 @@ ansi-styles@^5.0.0:
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
   integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
 
-ansi-styles@^6.1.0:
+ansi-styles@^6.0.0, ansi-styles@^6.1.0:
   version "6.2.1"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
   integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
@@ -5740,6 +5964,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0:
   resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
   integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==
 
+assertion-error@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
+  integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
+
 assign-symbols@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
@@ -6391,6 +6620,11 @@ bytes@3.1.2:
   resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
   integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
 
+cac@^6.7.14:
+  version "6.7.14"
+  resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959"
+  integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==
+
 cacache@17.0.4, cacache@^17.0.0:
   version "17.0.4"
   resolved "https://registry.yarnpkg.com/cacache/-/cacache-17.0.4.tgz#5023ed892ba8843e3b7361c26d0ada37e146290c"
@@ -6545,6 +6779,19 @@ caseless@~0.12.0:
   resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
   integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==
 
+chai@^4.3.7:
+  version "4.3.7"
+  resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51"
+  integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==
+  dependencies:
+    assertion-error "^1.1.0"
+    check-error "^1.0.2"
+    deep-eql "^4.1.2"
+    get-func-name "^2.0.0"
+    loupe "^2.3.1"
+    pathval "^1.1.1"
+    type-detect "^4.0.5"
+
 chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
@@ -6622,6 +6869,11 @@ check-disk-space@3.3.1:
   resolved "https://registry.yarnpkg.com/check-disk-space/-/check-disk-space-3.3.1.tgz#10c4c8706fdd16d3e5c3572a16aa95efd0b4d40b"
   integrity sha512-iOrT8yCZjSnyNZ43476FE2rnssvgw5hnuwOM0hm8Nj1qa0v4ieUUEbCyxxsEliaoDUb/75yCOL71zkDiDBLbMQ==
 
+check-error@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
+  integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==
+
 cheerio-select@^1.5.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.6.0.tgz#489f36604112c722afa147dedd0d4609c09e1696"
@@ -6814,6 +7066,14 @@ cli-truncate@^2.1.0:
     slice-ansi "^3.0.0"
     string-width "^4.2.0"
 
+cli-truncate@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389"
+  integrity sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==
+  dependencies:
+    slice-ansi "^5.0.0"
+    string-width "^5.0.0"
+
 cli-width@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
@@ -7746,6 +8006,13 @@ dedent@^0.7.0:
   resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
   integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==
 
+deep-eql@^4.1.2:
+  version "4.1.3"
+  resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d"
+  integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==
+  dependencies:
+    type-detect "^4.0.0"
+
 deep-extend@^0.6.0:
   version "0.6.0"
   resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
@@ -7946,6 +8213,11 @@ diff@^4.0.1:
   resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
   integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
 
+diff@^5.1.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40"
+  integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==
+
 dir-glob@^3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
@@ -8424,6 +8696,34 @@ esbuild@0.17.8:
     "@esbuild/win32-ia32" "0.17.8"
     "@esbuild/win32-x64" "0.17.8"
 
+esbuild@^0.16.14:
+  version "0.16.17"
+  resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.16.17.tgz#fc2c3914c57ee750635fee71b89f615f25065259"
+  integrity sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==
+  optionalDependencies:
+    "@esbuild/android-arm" "0.16.17"
+    "@esbuild/android-arm64" "0.16.17"
+    "@esbuild/android-x64" "0.16.17"
+    "@esbuild/darwin-arm64" "0.16.17"
+    "@esbuild/darwin-x64" "0.16.17"
+    "@esbuild/freebsd-arm64" "0.16.17"
+    "@esbuild/freebsd-x64" "0.16.17"
+    "@esbuild/linux-arm" "0.16.17"
+    "@esbuild/linux-arm64" "0.16.17"
+    "@esbuild/linux-ia32" "0.16.17"
+    "@esbuild/linux-loong64" "0.16.17"
+    "@esbuild/linux-mips64el" "0.16.17"
+    "@esbuild/linux-ppc64" "0.16.17"
+    "@esbuild/linux-riscv64" "0.16.17"
+    "@esbuild/linux-s390x" "0.16.17"
+    "@esbuild/linux-x64" "0.16.17"
+    "@esbuild/netbsd-x64" "0.16.17"
+    "@esbuild/openbsd-x64" "0.16.17"
+    "@esbuild/sunos-x64" "0.16.17"
+    "@esbuild/win32-arm64" "0.16.17"
+    "@esbuild/win32-ia32" "0.16.17"
+    "@esbuild/win32-x64" "0.16.17"
+
 esbuild@^0.17.0:
   version "0.17.11"
   resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.11.tgz#9f3122643b21d7e7731e42f18576c10bfa28152b"
@@ -9343,6 +9643,11 @@ get-css-data@^2.0.2:
   resolved "https://registry.yarnpkg.com/get-css-data/-/get-css-data-2.1.0.tgz#4d53e5255d98b553577cb80b8ca1f2e114aef602"
   integrity sha512-HtPrzGk8aBF9rLeQNuImcXci7YVqsMEKzVflEWaCJu25ehxyDNiZRWoSxqSFUBfma8LERqKo70t/TcaGjIsM9g==
 
+get-func-name@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
+  integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==
+
 get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f"
@@ -10710,6 +11015,11 @@ is-fullwidth-code-point@^3.0.0:
   resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
   integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
 
+is-fullwidth-code-point@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88"
+  integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==
+
 is-generator-fn@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
@@ -12191,6 +12501,11 @@ loader-utils@^2.0.0:
     emojis-list "^3.0.0"
     json5 "^2.1.2"
 
+local-pkg@^0.4.2:
+  version "0.4.3"
+  resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.4.3.tgz#0ff361ab3ae7f1c19113d9bb97b98b905dbc4963"
+  integrity sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==
+
 locate-path@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
@@ -12410,6 +12725,13 @@ loose-envify@^1.0.0, loose-envify@^1.4.0:
   dependencies:
     js-tokens "^3.0.0 || ^4.0.0"
 
+loupe@^2.3.1, loupe@^2.3.6:
+  version "2.3.6"
+  resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53"
+  integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==
+  dependencies:
+    get-func-name "^2.0.0"
+
 lower-case-first@^2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-2.0.2.tgz#64c2324a2250bf7c37c5901e76a5b5309301160b"
@@ -13337,6 +13659,16 @@ mkdirp@^2.1.3:
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.5.tgz#78d7eaf15e069ba7b6b47d76dd94cfadf7a4062f"
   integrity sha512-jbjfql+shJtAPrFoKxHOXip4xS+kul9W3OzfzzrqueWK2QMGon2bFH2opl6W9EagBThjEz+iysyi/swOoVfB/w==
 
+mlly@^1.1.0, mlly@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.1.1.tgz#f1838b14795e2cc284aa4ebcc76a258a52e6f537"
+  integrity sha512-Jnlh4W/aI4GySPo6+DyTN17Q75KKbLTyFK8BrGhjNP4rxuUjbRWhE6gHg3bs33URWAF44FRm7gdQA348i3XxRw==
+  dependencies:
+    acorn "^8.8.2"
+    pathe "^1.1.0"
+    pkg-types "^1.0.1"
+    ufo "^1.1.0"
+
 modern-normalize@1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/modern-normalize/-/modern-normalize-1.1.0.tgz#da8e80140d9221426bd4f725c6e11283d34f90b7"
@@ -14261,6 +14593,13 @@ p-limit@^2.0.0, p-limit@^2.2.0:
   dependencies:
     p-try "^2.0.0"
 
+p-limit@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644"
+  integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==
+  dependencies:
+    yocto-queue "^1.0.0"
+
 p-locate@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
@@ -14668,6 +15007,16 @@ path@^0.12.7:
     process "^0.11.1"
     util "^0.10.3"
 
+pathe@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.0.tgz#e2e13f6c62b31a3289af4ba19886c230f295ec03"
+  integrity sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==
+
+pathval@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d"
+  integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==
+
 peek-readable@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-4.1.0.tgz#4ece1111bf5c2ad8867c314c81356847e8a62e72"
@@ -14714,7 +15063,7 @@ pg-types@^2.1.0, pg-types@^2.2.0:
     postgres-date "~1.0.4"
     postgres-interval "^1.1.0"
 
-pg@^8.4.0:
+pg@^8.10.0, pg@^8.4.0:
   version "8.10.0"
   resolved "https://registry.yarnpkg.com/pg/-/pg-8.10.0.tgz#5b8379c9b4a36451d110fc8cd98fc325fe62ad24"
   integrity sha512-ke7o7qSTMb47iwzOSaZMfeR7xToFdkE71ifIipOAAaLIM0DYzfOAXlgFFmYUIE2BcJtvnVlGCID84ZzCegE8CQ==
@@ -14806,6 +15155,15 @@ pkg-dir@^5.0.0:
   dependencies:
     find-up "^5.0.0"
 
+pkg-types@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.0.2.tgz#c233efc5210a781e160e0cafd60c0d0510a4b12e"
+  integrity sha512-hM58GKXOcj8WTqUXnsQyJYXdeAPbythQgEF3nTcEo+nkD49chjQ9IKm/QJy9xf6JakXptz86h7ecP2024rrLaQ==
+  dependencies:
+    jsonc-parser "^3.2.0"
+    mlly "^1.1.1"
+    pathe "^1.1.0"
+
 please-upgrade-node@^3.2.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
@@ -14878,7 +15236,7 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
   resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
   integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
 
-postcss@8.4.21, postcss@^8.2.14, postcss@^8.3.7, postcss@^8.4.16, postcss@^8.4.19:
+postcss@8.4.21, postcss@^8.2.14, postcss@^8.3.7, postcss@^8.4.16, postcss@^8.4.19, postcss@^8.4.21:
   version "8.4.21"
   resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4"
   integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==
@@ -14937,6 +15295,15 @@ pretty-bytes@^5.3.0:
   resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
   integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==
 
+pretty-format@^27.5.1:
+  version "27.5.1"
+  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e"
+  integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==
+  dependencies:
+    ansi-regex "^5.0.1"
+    ansi-styles "^5.0.0"
+    react-is "^17.0.1"
+
 pretty-format@^29.0.0, pretty-format@^29.5.0:
   version "29.5.0"
   resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.5.0.tgz#283134e74f70e2e3e7229336de0e4fce94ccde5a"
@@ -15467,6 +15834,11 @@ react-is@^16.13.1, react-is@^16.7.0:
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
   integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
 
+react-is@^17.0.1:
+  version "17.0.2"
+  resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
+  integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
+
 react-is@^18.0.0:
   version "18.2.0"
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
@@ -16070,7 +16442,7 @@ rollup@^2.40.0:
   optionalDependencies:
     fsevents "~2.3.2"
 
-rollup@^3.0.0:
+rollup@^3.0.0, rollup@^3.10.0:
   version "3.18.0"
   resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.18.0.tgz#2354ba63ba66d6a09c652c3ea0dbcd9dad72bbde"
   integrity sha512-J8C6VfEBjkvYPESMQYxKHxNOh4A5a3FlP+0BETGo34HEcE4eTlgCrO2+eWzlu2a/sHs2QUkZco+wscH7jhhgWg==
@@ -16429,6 +16801,11 @@ side-channel@^1.0.4:
     get-intrinsic "^1.0.2"
     object-inspect "^1.9.0"
 
+siginfo@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30"
+  integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==
+
 sigmund@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
@@ -16511,6 +16888,14 @@ slice-ansi@^4.0.0:
     astral-regex "^2.0.0"
     is-fullwidth-code-point "^3.0.0"
 
+slice-ansi@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a"
+  integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==
+  dependencies:
+    ansi-styles "^6.0.0"
+    is-fullwidth-code-point "^4.0.0"
+
 slick@^1.12.2:
   version "1.12.2"
   resolved "https://registry.yarnpkg.com/slick/-/slick-1.12.2.tgz#bd048ddb74de7d1ca6915faa4a57570b3550c2d7"
@@ -16829,7 +17214,12 @@ sql.js@1.3.2:
   resolved "https://registry.yarnpkg.com/sql.js/-/sql.js-1.3.2.tgz#ce0c7b9d884a7f50476e4c2fb29093e10a83ab09"
   integrity sha512-vRdzoj4TCrCX8yI2mv0OVVEuOOz2IlhEfw1x1Q65BhpmLep46iu+M04zxln4u2mHRk+wj7avFq2L3/1gQS1orQ==
 
-sqlite3@^5.0.0:
+sql.js@1.8.0:
+  version "1.8.0"
+  resolved "https://registry.yarnpkg.com/sql.js/-/sql.js-1.8.0.tgz#cb45d957e17a2239662fe2f614c9b678990867a6"
+  integrity sha512-3HD8pSkZL+5YvYUI8nlvNILs61ALqq34xgmF+BHpqxe68yZIJ1H+sIVIODvni25+CcxHUxDyrTJUL0lE/m7afw==
+
+sqlite3@^5.1.4:
   version "5.1.4"
   resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.1.4.tgz#35f83d368963168b324ad2f0fffce09f3b8723a7"
   integrity sha512-i0UlWAzPlzX3B5XP2cYuhWQJsTtlMD6obOa1PgeEQ4DHEXUuyJkgv50I3isqZAP5oFc2T8OFvakmDh2W6I+YpA==
@@ -16893,6 +17283,11 @@ stack-utils@^2.0.3:
   dependencies:
     escape-string-regexp "^2.0.0"
 
+stackback@0.0.2:
+  version "0.0.2"
+  resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b"
+  integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==
+
 standard-as-callback@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45"
@@ -16916,6 +17311,11 @@ statuses@2.0.1:
   resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
   integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
 
+std-env@^3.3.1:
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.3.2.tgz#af27343b001616015534292178327b202b9ee955"
+  integrity sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==
+
 stream-exhaust@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz#acdac8da59ef2bc1e17a2c0ccf6c320d120e555d"
@@ -16998,7 +17398,7 @@ string-width@^3.0.0, string-width@^3.1.0:
     is-fullwidth-code-point "^2.0.0"
     strip-ansi "^5.1.0"
 
-string-width@^5.0.1:
+string-width@^5.0.0, string-width@^5.0.1:
   version "5.1.2"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
   integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
@@ -17122,6 +17522,13 @@ strip-json-comments@~2.0.1:
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
   integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==
 
+strip-literal@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-1.0.1.tgz#0115a332710c849b4e46497891fb8d585e404bd2"
+  integrity sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==
+  dependencies:
+    acorn "^8.8.2"
+
 stripe@^8.197.0:
   version "8.222.0"
   resolved "https://registry.yarnpkg.com/stripe/-/stripe-8.222.0.tgz#5f159156e411b668a88b8f957df5ac3c63b119de"
@@ -17414,6 +17821,21 @@ time-stamp@^1.0.0:
   resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3"
   integrity sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw==
 
+tinybench@^2.3.1:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.4.0.tgz#83f60d9e5545353610fe7993bd783120bc20c7a7"
+  integrity sha512-iyziEiyFxX4kyxSp+MtY1oCH/lvjH3PxFN8PGCDeqcZWAJ/i+9y+nL85w99PxVzrIvew/GSkSbDYtiGVa85Afg==
+
+tinypool@^0.3.1:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.3.1.tgz#a99c2e446aba9be05d3e1cb756d6aed7af4723b6"
+  integrity sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ==
+
+tinyspy@^1.0.2:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-1.1.1.tgz#0cb91d5157892af38cb2d217f5c7e8507a5bf092"
+  integrity sha512-UVq5AXt/gQlti7oxoIg5oi/9r0WpF7DGEVwXgqWSMmyN16+e3tl5lIvTaOpJ3TAtu5xFzWccFRM4R5NaWHF+4g==
+
 title-case@^3.0.3:
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/title-case/-/title-case-3.0.3.tgz#bc689b46f02e411f1d1e1d081f7c3deca0489982"
@@ -17663,7 +18085,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
   resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
   integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==
 
-type-detect@4.0.8:
+type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5:
   version "4.0.8"
   resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
   integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
@@ -17785,6 +18207,11 @@ ua-parser-js@^0.7.30:
   resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.34.tgz#afb439e2e3e394bdc90080acb661a39c685b67d7"
   integrity sha512-cJMeh/eOILyGu0ejgTKB95yKT3zOenSe9UGE3vj6WfiOwgGYnmATUsnDixMFvdU+rNMvWih83hrUP8VwhF9yXQ==
 
+ufo@^1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.1.1.tgz#e70265e7152f3aba425bd013d150b2cdf4056d7c"
+  integrity sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==
+
 uglify-js@^3.1.4, uglify-js@^3.5.1:
   version "3.17.4"
   resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c"
@@ -17961,6 +18388,22 @@ unpipe@1.0.0, unpipe@~1.0.0:
   resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
   integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
 
+unplugin-swc@^1.3.2:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/unplugin-swc/-/unplugin-swc-1.3.2.tgz#4c859896ce33a46f66033ba66290b33fb886a248"
+  integrity sha512-x0+NTM4NR1jWpailVhK5sXO9svyL4iWZ+yah0WZ1G+SaI1hPysa95nVSzXqLP7y4+MKTO17wP+EVqjrREqgBsw==
+  dependencies:
+    unplugin "^0.6.0"
+
+unplugin@^0.6.0:
+  version "0.6.3"
+  resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-0.6.3.tgz#b8721e2b163a410a7efed726e6a0fc6fbadf975a"
+  integrity sha512-CoW88FQfCW/yabVc4bLrjikN9HC8dEvMU4O7B6K2jsYMPK0l6iAnd9dpJwqGcmXJKRCU9vwSsy653qg+RK0G6A==
+  dependencies:
+    chokidar "^3.5.3"
+    webpack-sources "^3.2.3"
+    webpack-virtual-modules "^0.4.3"
+
 unset-value@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
@@ -18218,6 +18661,60 @@ vinyl@^2.0.0:
     remove-trailing-separator "^1.0.1"
     replace-ext "^1.0.0"
 
+vite-node@0.29.2:
+  version "0.29.2"
+  resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.29.2.tgz#463626197e248971774075faf3d6896c29cf8062"
+  integrity sha512-5oe1z6wzI3gkvc4yOBbDBbgpiWiApvuN4P55E8OI131JGrSuo4X3SOZrNmZYo4R8Zkze/dhi572blX0zc+6SdA==
+  dependencies:
+    cac "^6.7.14"
+    debug "^4.3.4"
+    mlly "^1.1.0"
+    pathe "^1.1.0"
+    picocolors "^1.0.0"
+    vite "^3.0.0 || ^4.0.0"
+
+"vite@^3.0.0 || ^4.0.0":
+  version "4.1.4"
+  resolved "https://registry.yarnpkg.com/vite/-/vite-4.1.4.tgz#170d93bcff97e0ebc09764c053eebe130bfe6ca0"
+  integrity sha512-3knk/HsbSTKEin43zHu7jTwYWv81f8kgAL99G5NWBcA1LKvtvcVAC4JjBH1arBunO9kQka+1oGbrMKOjk4ZrBg==
+  dependencies:
+    esbuild "^0.16.14"
+    postcss "^8.4.21"
+    resolve "^1.22.1"
+    rollup "^3.10.0"
+  optionalDependencies:
+    fsevents "~2.3.2"
+
+vitest@^0.29.2:
+  version "0.29.2"
+  resolved "https://registry.yarnpkg.com/vitest/-/vitest-0.29.2.tgz#0376b547169ddefbde3fbc040b48569ec61d6179"
+  integrity sha512-ydK9IGbAvoY8wkg29DQ4ivcVviCaUi3ivuPKfZEVddMTenFHUfB8EEDXQV8+RasEk1ACFLgMUqAaDuQ/Nk+mQA==
+  dependencies:
+    "@types/chai" "^4.3.4"
+    "@types/chai-subset" "^1.3.3"
+    "@types/node" "*"
+    "@vitest/expect" "0.29.2"
+    "@vitest/runner" "0.29.2"
+    "@vitest/spy" "0.29.2"
+    "@vitest/utils" "0.29.2"
+    acorn "^8.8.1"
+    acorn-walk "^8.2.0"
+    cac "^6.7.14"
+    chai "^4.3.7"
+    debug "^4.3.4"
+    local-pkg "^0.4.2"
+    pathe "^1.1.0"
+    picocolors "^1.0.0"
+    source-map "^0.6.1"
+    std-env "^3.3.1"
+    strip-literal "^1.0.0"
+    tinybench "^2.3.1"
+    tinypool "^0.3.1"
+    tinyspy "^1.0.2"
+    vite "^3.0.0 || ^4.0.0"
+    vite-node "0.29.2"
+    why-is-node-running "^2.2.2"
+
 void-elements@^2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
@@ -18397,6 +18894,11 @@ webpack-subresource-integrity@5.1.0:
   dependencies:
     typed-assert "^1.0.8"
 
+webpack-virtual-modules@^0.4.3:
+  version "0.4.6"
+  resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.4.6.tgz#3e4008230731f1db078d9cb6f68baf8571182b45"
+  integrity sha512-5tyDlKLqPfMqjT3Q9TAqf2YqjwmnUleZwzJi1A5qXnlBCdj2AtOJ6wAWdglTIDOPgOiOrXeBeFcsQ8+aGQ6QbA==
+
 webpack@5.75.0:
   version "5.75.0"
   resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152"
@@ -18527,6 +19029,14 @@ which@^3.0.0:
   dependencies:
     isexe "^2.0.0"
 
+why-is-node-running@^2.2.2:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.2.2.tgz#4185b2b4699117819e7154594271e7e344c9973e"
+  integrity sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==
+  dependencies:
+    siginfo "^2.0.0"
+    stackback "0.0.2"
+
 wide-align@^1.1.0, wide-align@^1.1.2, wide-align@^1.1.5:
   version "1.1.5"
   resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
@@ -18929,6 +19439,11 @@ yocto-queue@^0.1.0:
   resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
   integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
 
+yocto-queue@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251"
+  integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==
+
 zen-observable-ts@^1.2.5:
   version "1.2.5"
   resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz#6c6d9ea3d3a842812c6e9519209365a122ba8b58"