From dfddce02e6b41c65893d981a4bd87e249f01deb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Sans=C3=B3n?= <57395395+csansoon@users.noreply.github.com> Date: Thu, 18 Jul 2024 09:49:42 +0200 Subject: [PATCH] Setup core vitest (#43) --- packages/core/package.json | 8 +- packages/core/src/tests/factories/commits.ts | 20 ++ packages/core/src/tests/factories/index.ts | 4 + packages/core/src/tests/factories/projects.ts | 57 +++++ packages/core/src/tests/factories/users.ts | 22 ++ .../core/src/tests/factories/workspaces.ts | 28 +++ packages/core/src/tests/setup.ts | 12 + packages/core/src/tests/tmp.test.ts | 8 + packages/core/src/tests/useTestDatabase.ts | 22 ++ packages/core/src/tests/vitest.d.ts | 9 + packages/core/vitest.config.mjs | 19 ++ packages/env/src/index.ts | 2 +- pnpm-lock.yaml | 208 +++++++++++++++++- 13 files changed, 405 insertions(+), 14 deletions(-) create mode 100644 packages/core/src/tests/factories/commits.ts create mode 100644 packages/core/src/tests/factories/index.ts create mode 100644 packages/core/src/tests/factories/projects.ts create mode 100644 packages/core/src/tests/factories/users.ts create mode 100644 packages/core/src/tests/factories/workspaces.ts create mode 100644 packages/core/src/tests/setup.ts create mode 100644 packages/core/src/tests/tmp.test.ts create mode 100644 packages/core/src/tests/useTestDatabase.ts create mode 100644 packages/core/src/tests/vitest.d.ts create mode 100644 packages/core/vitest.config.mjs diff --git a/packages/core/package.json b/packages/core/package.json index da9828700..4a395ee4c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -18,6 +18,7 @@ "db:studio": "drizzle-kit studio --port 3002", "lint": "eslint src", "tc": "tsc --noEmit", + "test": "pnpm run db:migrate:test && vitest run --pool=forks", "test:watch": "vitest", "prettier": "prettier --write src/**/*.ts" }, @@ -29,12 +30,17 @@ "zod": "^3.23.8" }, "devDependencies": { + "@faker-js/faker": "^8.4.1", "@latitude-data/eslint-config": "workspace:*", "@latitude-data/typescript-config": "workspace:*", "@types/bcrypt": "^5.0.2", "@types/lodash-es": "^4.17.12", "@types/node": "^20.14.10", "drizzle-kit": "^0.22.8", - "eslint-plugin-drizzle": "^0.2.3" + "eslint-plugin-drizzle": "^0.2.3", + "pg-transactional-tests": "^1.0.9", + "supertest": "^7.0.0", + "vite-tsconfig-paths": "^4.3.2", + "vitest": "^2.0.3" } } diff --git a/packages/core/src/tests/factories/commits.ts b/packages/core/src/tests/factories/commits.ts new file mode 100644 index 000000000..6db629597 --- /dev/null +++ b/packages/core/src/tests/factories/commits.ts @@ -0,0 +1,20 @@ +import { Project } from '$core/schema' +import createCommitFn from '$core/services/commits/create' + +import { createProject, ICreateProject } from './projects' + +export type ICreateDraft = { + project?: Project | ICreateProject +} +export async function createDraft(commitData: Partial = {}) { + let project = commitData.project ?? {} + if (!('id' in project)) { + const { project: newProject } = await createProject(project) + project = newProject + } + + const result = await createCommitFn({ projectId: (project as Project).id }) + const commit = result.unwrap() + + return { commit } +} diff --git a/packages/core/src/tests/factories/index.ts b/packages/core/src/tests/factories/index.ts new file mode 100644 index 000000000..29da19130 --- /dev/null +++ b/packages/core/src/tests/factories/index.ts @@ -0,0 +1,4 @@ +export * from './users' +export * from './workspaces' +export * from './projects' +export * from './commits' diff --git a/packages/core/src/tests/factories/projects.ts b/packages/core/src/tests/factories/projects.ts new file mode 100644 index 000000000..fa629e9c5 --- /dev/null +++ b/packages/core/src/tests/factories/projects.ts @@ -0,0 +1,57 @@ +import { faker } from '@faker-js/faker' +import { database as db } from '$core/client' +import { getUser } from '$core/data-access' +import { Result, Transaction } from '$core/lib' +import { Project, projects, Workspace, type SafeUser } from '$core/schema' + +import { createWorkspace, type ICreateWorkspace } from './workspaces' + +// TODO: Replace with actual service +const createProjectFn = ({ + name, + workspaceId, +}: { + name: string + workspaceId: number +}) => { + return Transaction.call(async (tx) => { + const insertedProjects = await tx + .insert(projects) + .values({ name, workspaceId }) + .returning() + + const newProject = insertedProjects[0]! + + return Result.ok(newProject) + }, db) +} + +export type ICreateProject = { + name?: string + workspace?: Workspace | ICreateWorkspace +} +export async function createProject(projectData: Partial = {}) { + let workspaceData = projectData.workspace ?? {} + let user: SafeUser + let workspace: Workspace + + if ('id' in workspaceData) { + user = (await getUser(workspaceData.creatorId!)) as SafeUser + workspace = workspaceData as Workspace + } else { + const newWorkspace = await createWorkspace(workspaceData) + workspace = newWorkspace.workspace + user = newWorkspace.userData + } + + const randomName = faker.commerce.department() + const { name } = projectData + + const result = await createProjectFn({ + name: name ?? randomName, + workspaceId: workspace.id, + }) + const project = result.unwrap() + + return { project, user, workspace } +} diff --git a/packages/core/src/tests/factories/users.ts b/packages/core/src/tests/factories/users.ts new file mode 100644 index 000000000..ed329d504 --- /dev/null +++ b/packages/core/src/tests/factories/users.ts @@ -0,0 +1,22 @@ +import { faker } from '@faker-js/faker' +import { createUser as createUserFn } from '$core/services/users/createUser' + +function makeRandomUserData() { + return { + name: faker.person.firstName(), + email: faker.internet.email(), + password: faker.internet.password(), + } +} +export type ICreateUser = { + name?: string + email?: string + password?: string +} +export async function createUser(userData: Partial = {}) { + const randomUserData = makeRandomUserData() + const data = { ...randomUserData, ...userData } + + const result = await createUserFn(data) + return result.unwrap() +} diff --git a/packages/core/src/tests/factories/workspaces.ts b/packages/core/src/tests/factories/workspaces.ts new file mode 100644 index 000000000..84d531fbc --- /dev/null +++ b/packages/core/src/tests/factories/workspaces.ts @@ -0,0 +1,28 @@ +import { faker } from '@faker-js/faker' +import { type SafeUser } from '$core/schema' +import { createWorkspace as createWorkspaceFn } from '$core/services/workspaces/create' + +import { createUser, type ICreateUser } from './users' + +export type ICreateWorkspace = { + name?: string + creator?: SafeUser | ICreateUser +} +export async function createWorkspace( + workspaceData: Partial = {}, +) { + let userData = workspaceData.creator ?? {} + if (!('id' in userData)) { + userData = await createUser(userData) + } + + const randomName = faker.company.name() + const { name } = workspaceData + const result = await createWorkspaceFn({ + name: name ?? randomName, + creatorId: userData.id, + }) + const workspace = result.unwrap() + + return { workspace, userData } +} diff --git a/packages/core/src/tests/setup.ts b/packages/core/src/tests/setup.ts new file mode 100644 index 000000000..3a9239329 --- /dev/null +++ b/packages/core/src/tests/setup.ts @@ -0,0 +1,12 @@ +// vitest-env.d.ts +import { beforeEach } from 'vitest' + +import * as factories from './factories' +import useTestDatabase from './useTestDatabase' + +// This do rollback stragegy for each test. Faster than truncate. +useTestDatabase() + +beforeEach((ctx) => { + ctx.factories = factories +}) diff --git a/packages/core/src/tests/tmp.test.ts b/packages/core/src/tests/tmp.test.ts new file mode 100644 index 000000000..2382870c5 --- /dev/null +++ b/packages/core/src/tests/tmp.test.ts @@ -0,0 +1,8 @@ +import { describe, expect, it } from 'vitest' + +// TODO: Remove when adding an actual test suite +describe('placeholder', () => { + it('works', () => { + expect(true).toBe(true) + }) +}) diff --git a/packages/core/src/tests/useTestDatabase.ts b/packages/core/src/tests/useTestDatabase.ts new file mode 100644 index 000000000..97e0ba46d --- /dev/null +++ b/packages/core/src/tests/useTestDatabase.ts @@ -0,0 +1,22 @@ +import { + close, + patchPgForTransactions, + rollbackTransaction, + startTransaction, + unpatchPgForTransactions, +} from 'pg-transactional-tests' +import { afterAll, afterEach, beforeAll, beforeEach } from 'vitest' + +export default function useTestDatabase() { + beforeAll(async () => { + patchPgForTransactions() + await startTransaction() + }) + beforeEach(startTransaction) + afterEach(rollbackTransaction) + afterAll(async () => { + await rollbackTransaction() + unpatchPgForTransactions() + await close() + }) +} diff --git a/packages/core/src/tests/vitest.d.ts b/packages/core/src/tests/vitest.d.ts new file mode 100644 index 000000000..a176079c9 --- /dev/null +++ b/packages/core/src/tests/vitest.d.ts @@ -0,0 +1,9 @@ +import 'vitest' + +import * as factories from './factories' + +declare module 'vitest' { + export interface TestContext { + factories: typeof factories + } +} diff --git a/packages/core/vitest.config.mjs b/packages/core/vitest.config.mjs new file mode 100644 index 000000000..a7ee55fe9 --- /dev/null +++ b/packages/core/vitest.config.mjs @@ -0,0 +1,19 @@ +/// +import { fileURLToPath } from 'url' +import { dirname } from 'path' +import { defineConfig } from 'vitest/config' +import tsconfigPaths from 'vite-tsconfig-paths' + +const filename = fileURLToPath(import.meta.url) +const root = dirname(filename) + +export default defineConfig({ + plugins: [tsconfigPaths({ root })], + test: { + globals: true, + testTimeout: 5000, + environment: 'node', + setupFiles: ['./src/tests/setup.ts'], + include: ['./src/**/*.test.ts'], + }, +}) \ No newline at end of file diff --git a/packages/env/src/index.ts b/packages/env/src/index.ts index 2a3526b69..133abb9eb 100644 --- a/packages/env/src/index.ts +++ b/packages/env/src/index.ts @@ -6,7 +6,7 @@ const env = process.env.NODE_ENV || 'development' if (env !== 'production') { dotenv.populate(process.env as DotenvPopulateInput, { NODE_ENV: env, - DATABASE_URL: `postgres://latitude:secret@localhost:5432/latitude_development`, + DATABASE_URL: `postgres://latitude:secret@localhost:5432/latitude_${env}`, ELASTIC_URL: 'https://elastic:9200', ELASTIC_USERNAME: 'latitude', ELASTIC_PASSWORD: 'secret', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3f7a2d573..b9b0ea05c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -322,6 +322,9 @@ importers: specifier: ^3.23.8 version: 3.23.8 devDependencies: + '@faker-js/faker': + specifier: ^8.4.1 + version: 8.4.1 '@latitude-data/eslint-config': specifier: workspace:* version: link:../../tools/eslint @@ -343,6 +346,18 @@ importers: eslint-plugin-drizzle: specifier: ^0.2.3 version: 0.2.3(eslint@9.6.0) + pg-transactional-tests: + specifier: ^1.0.9 + version: 1.0.9(pg@8.12.0) + supertest: + specifier: ^7.0.0 + version: 7.0.0 + vite-tsconfig-paths: + specifier: ^4.3.2 + version: 4.3.2(typescript@5.5.3) + vitest: + specifier: ^2.0.3 + version: 2.0.3(@types/node@20.14.10) packages/env: dependencies: @@ -3723,6 +3738,21 @@ packages: chai: 4.4.1 dev: true + /@vitest/expect@2.0.3: + resolution: {integrity: sha512-X6AepoOYePM0lDNUPsGXTxgXZAl3EXd0GYe/MZyVE4HzkUqyUVC6S3PrY5mClDJ6/7/7vALLMV3+xD/Ko60Hqg==} + dependencies: + '@vitest/spy': 2.0.3 + '@vitest/utils': 2.0.3 + chai: 5.1.1 + tinyrainbow: 1.2.0 + dev: true + + /@vitest/pretty-format@2.0.3: + resolution: {integrity: sha512-URM4GLsB2xD37nnTyvf6kfObFafxmycCL8un3OC9gaCs5cti2u+5rJdIflZ2fUJUen4NbvF6jCufwViAFLvz1g==} + dependencies: + tinyrainbow: 1.2.0 + dev: true + /@vitest/runner@1.6.0: resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} dependencies: @@ -3731,6 +3761,13 @@ packages: pathe: 1.1.2 dev: true + /@vitest/runner@2.0.3: + resolution: {integrity: sha512-EmSP4mcjYhAcuBWwqgpjR3FYVeiA4ROzRunqKltWjBfLNs1tnMLtF+qtgd5ClTwkDP6/DGlKJTNa6WxNK0bNYQ==} + dependencies: + '@vitest/utils': 2.0.3 + pathe: 1.1.2 + dev: true + /@vitest/snapshot@1.6.0: resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} dependencies: @@ -3739,12 +3776,26 @@ packages: pretty-format: 29.7.0 dev: true + /@vitest/snapshot@2.0.3: + resolution: {integrity: sha512-6OyA6v65Oe3tTzoSuRPcU6kh9m+mPL1vQ2jDlPdn9IQoUxl8rXhBnfICNOC+vwxWY684Vt5UPgtcA2aPFBb6wg==} + dependencies: + '@vitest/pretty-format': 2.0.3 + magic-string: 0.30.10 + pathe: 1.1.2 + dev: true + /@vitest/spy@1.6.0: resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} dependencies: tinyspy: 2.2.1 dev: true + /@vitest/spy@2.0.3: + resolution: {integrity: sha512-sfqyAw/ypOXlaj4S+w8689qKM1OyPOqnonqOc9T91DsoHbfN5mU7FdifWWv3MtQFf0lEUstEwR9L/q/M390C+A==} + dependencies: + tinyspy: 3.0.0 + dev: true + /@vitest/utils@1.6.0: resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} dependencies: @@ -3754,6 +3805,15 @@ packages: pretty-format: 29.7.0 dev: true + /@vitest/utils@2.0.3: + resolution: {integrity: sha512-c/UdELMuHitQbbc/EVctlBaxoYAwQPQdSNwv7z/vHyBKy2edYZaFgptE27BRueZB7eW8po+cllotMNTDpL3HWg==} + dependencies: + '@vitest/pretty-format': 2.0.3 + estree-walker: 3.0.3 + loupe: 3.1.1 + tinyrainbow: 1.2.0 + dev: true + /abbrev@1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} dev: false @@ -4015,6 +4075,11 @@ packages: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} dev: true + /assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + dev: true + /ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} dev: true @@ -4220,6 +4285,17 @@ packages: type-detect: 4.0.8 dev: true + /chai@5.1.1: + resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==} + engines: {node: '>=12'} + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.1 + pathval: 2.0.0 + dev: true + /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -4242,6 +4318,11 @@ packages: get-func-name: 2.0.2 dev: true + /check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + dev: true + /chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -4522,6 +4603,11 @@ packages: type-detect: 4.0.8 dev: true + /deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + dev: true + /deep-equal@2.2.3: resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} engines: {node: '>= 0.4'} @@ -6695,6 +6781,12 @@ packages: get-func-name: 2.0.2 dev: true + /loupe@3.1.1: + resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==} + dependencies: + get-func-name: 2.0.2 + dev: true + /lru-cache@10.4.0: resolution: {integrity: sha512-bfJaPTuEiTYBu+ulDaeQ0F+uLmlfFkMgXj4cbwfuMSjgObGMzb55FMMbDvbRU0fAHZ4sLGkz2mKwcMg8Dvm8Ww==} engines: {node: '>=18'} @@ -7339,6 +7431,11 @@ packages: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} dev: true + /pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + dev: true + /periscopic@3.1.0: resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} dependencies: @@ -7350,12 +7447,10 @@ packages: /pg-cloudflare@1.1.1: resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==} requiresBuild: true - dev: false optional: true /pg-connection-string@2.6.4: resolution: {integrity: sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==} - dev: false /pg-int8@1.0.1: resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} @@ -7371,11 +7466,18 @@ packages: pg: '>=8.0' dependencies: pg: 8.12.0 - dev: false /pg-protocol@1.6.1: resolution: {integrity: sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==} + /pg-transactional-tests@1.0.9(pg@8.12.0): + resolution: {integrity: sha512-u9dFWZDWyycxtfD3SXFHhN2X8lcqA8Dg9M4CIv8OH4AyEaQhL2VE46am/yQxHnKTqgMw1SnejUjIJDZr20Vx1w==} + peerDependencies: + pg: '*' + dependencies: + pg: 8.12.0 + dev: true + /pg-types@2.2.0: resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} engines: {node: '>=4'} @@ -7385,7 +7487,6 @@ packages: postgres-bytea: 1.0.0 postgres-date: 1.0.7 postgres-interval: 1.2.0 - dev: false /pg-types@4.0.2: resolution: {integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==} @@ -7415,13 +7516,11 @@ packages: pgpass: 1.0.5 optionalDependencies: pg-cloudflare: 1.1.1 - dev: false /pgpass@1.0.5: resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} dependencies: split2: 4.2.0 - dev: false /picocolors@1.0.1: resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} @@ -7531,7 +7630,6 @@ packages: /postgres-array@2.0.0: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} - dev: false /postgres-array@3.0.2: resolution: {integrity: sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==} @@ -7540,7 +7638,6 @@ packages: /postgres-bytea@1.0.0: resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} engines: {node: '>=0.10.0'} - dev: false /postgres-bytea@3.0.0: resolution: {integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==} @@ -7551,7 +7648,6 @@ packages: /postgres-date@1.0.7: resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} engines: {node: '>=0.10.0'} - dev: false /postgres-date@2.1.0: resolution: {integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==} @@ -7562,7 +7658,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: xtend: 4.0.2 - dev: false /postgres-interval@3.0.0: resolution: {integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==} @@ -8193,7 +8288,6 @@ packages: /split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} - dev: false /stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -8530,11 +8624,26 @@ packages: engines: {node: '>=14.0.0'} dev: true + /tinypool@1.0.0: + resolution: {integrity: sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==} + engines: {node: ^18.0.0 || >=20.0.0} + dev: true + + /tinyrainbow@1.2.0: + resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} + engines: {node: '>=14.0.0'} + dev: true + /tinyspy@2.2.1: resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} engines: {node: '>=14.0.0'} dev: true + /tinyspy@3.0.0: + resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==} + engines: {node: '>=14.0.0'} + dev: true + /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} @@ -8926,6 +9035,27 @@ packages: - terser dev: true + /vite-node@2.0.3(@types/node@20.14.10): + resolution: {integrity: sha512-14jzwMx7XTcMB+9BhGQyoEAmSl0eOr3nrnn+Z12WNERtOvLN+d2scbRUvyni05rT3997Bg+rZb47NyP4IQPKXg==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.5 + pathe: 1.1.2 + tinyrainbow: 1.2.0 + vite: 5.3.3(@types/node@20.14.10) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /vite-tsconfig-paths@4.3.2(typescript@5.5.3): resolution: {integrity: sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==} peerDependencies: @@ -9034,6 +9164,61 @@ packages: - terser dev: true + /vitest@2.0.3(@types/node@20.14.10): + resolution: {integrity: sha512-o3HRvU93q6qZK4rI2JrhKyZMMuxg/JRt30E6qeQs6ueaiz5hr1cPj+Sk2kATgQzMMqsa2DiNI0TIK++1ULx8Jw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 2.0.3 + '@vitest/ui': 2.0.3 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@ampproject/remapping': 2.3.0 + '@types/node': 20.14.10 + '@vitest/expect': 2.0.3 + '@vitest/pretty-format': 2.0.3 + '@vitest/runner': 2.0.3 + '@vitest/snapshot': 2.0.3 + '@vitest/spy': 2.0.3 + '@vitest/utils': 2.0.3 + chai: 5.1.1 + debug: 4.3.5 + execa: 8.0.1 + magic-string: 0.30.10 + pathe: 1.1.2 + std-env: 3.7.0 + tinybench: 2.8.0 + tinypool: 1.0.0 + tinyrainbow: 1.2.0 + vite: 5.3.3(@types/node@20.14.10) + vite-node: 2.0.3(@types/node@20.14.10) + why-is-node-running: 2.3.0 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} @@ -9159,7 +9344,6 @@ packages: /xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} - dev: false /yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}