mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
queries in database, shared initalized with validate user as example
This commit is contained in:
parent
9f22e54957
commit
91ab2914c2
3
.github/file-filters.yml
vendored
3
.github/file-filters.yml
vendored
@ -36,6 +36,9 @@ backend: &backend
|
||||
config: &config
|
||||
- 'config-schema/**/*'
|
||||
|
||||
shared: &shared
|
||||
- 'shared/**/*'
|
||||
|
||||
database: &database
|
||||
- 'database/**/*'
|
||||
|
||||
|
||||
6
.github/workflows/test_database.yml
vendored
6
.github/workflows/test_database.yml
vendored
@ -35,7 +35,7 @@ jobs:
|
||||
|
||||
database_migration_test:
|
||||
if: needs.files-changed.outputs.database == 'true' || needs.files-changed.outputs.docker-compose == 'true' || needs.files-changed.outputs.mariadb == 'true'
|
||||
name: Database Migration Test - Up + Reset
|
||||
name: Database Migration Test - Up, Test + Reset
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -58,8 +58,8 @@ jobs:
|
||||
bun install --filter database --frozen-lockfile
|
||||
bun install --global --no-save turbo@^2
|
||||
|
||||
- name: Database | up
|
||||
run: turbo up
|
||||
- name: Database | up + test
|
||||
run: turbo test
|
||||
|
||||
- name: Database | reset
|
||||
run: turbo reset
|
||||
|
||||
44
.github/workflows/test_shared.yml
vendored
Normal file
44
.github/workflows/test_shared.yml
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
name: Gradido Shared Test CI
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Detect File Changes - Shared
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
shared: ${{ steps.changes.outputs.shared }}
|
||||
docker-compose: ${{ steps.changes.outputs.docker-compose }}
|
||||
database: ${{ steps.changes.outputs.database }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
|
||||
- name: Check for shared file changes
|
||||
uses: dorny/paths-filter@v2.11.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-filters.yml
|
||||
list-files: shell
|
||||
|
||||
build:
|
||||
name: Unit Tests, typecheck - Shared
|
||||
if: needs.files-changed.outputs.shared == 'true' || needs.files-changed.outputs.docker-compose == 'true' || needs.files-changed.outputs.database == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: install bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
|
||||
- name: install dependencies
|
||||
run: bun install --filter shared database --frozen-lockfile
|
||||
|
||||
- name: typecheck
|
||||
run: cd shared && yarn typecheck
|
||||
|
||||
- name: unit tests
|
||||
run: cd shared && yarn test
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -6,6 +6,8 @@
|
||||
vite.config.mjs.timestamp-*
|
||||
log4js-config*.json
|
||||
/node_modules/*
|
||||
node_modules
|
||||
build
|
||||
messages.pot
|
||||
nbproject
|
||||
.metadata
|
||||
|
||||
33
.vscode/launch.json
vendored
33
.vscode/launch.json
vendored
@ -4,6 +4,23 @@
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Database Debug Tests",
|
||||
"stopOnEntry": true,
|
||||
"runtimeExecutable": "yarn",
|
||||
"runtimeArgs": [
|
||||
"run",
|
||||
"test"
|
||||
],
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"cwd": "${workspaceFolder}/database"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
@ -86,6 +103,22 @@
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"cwd": "${workspaceFolder}/backend"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Shared Debug Test",
|
||||
"runtimeExecutable": "bun",
|
||||
"runtimeArgs": [
|
||||
"run",
|
||||
"test:debug"
|
||||
],
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"cwd": "${workspaceFolder}/shared"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -5,11 +5,10 @@ import { LOG4JS_GMS_CATEGORY_NAME } from '@/apis/gms/index'
|
||||
// import { createGmsUser } from '@/apis/gms/GmsClient'
|
||||
// import { GmsUser } from '@/apis/gms/model/GmsUser'
|
||||
import { CONFIG } from '@/config'
|
||||
import { getHomeCommunity } from '@/graphql/resolver/util/communities'
|
||||
import { sendUserToGms } from '@/graphql/resolver/util/sendUserToGms'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { initLogging } from '@/server/logger'
|
||||
import { AppDatabase } from 'database'
|
||||
import { AppDatabase, getHomeCommunity } from 'database'
|
||||
import { getLogger } from 'log4js'
|
||||
|
||||
const logger = getLogger(`${LOG4JS_GMS_CATEGORY_NAME}.ExportUsers`)
|
||||
@ -25,6 +24,9 @@ async function main() {
|
||||
await con.init()
|
||||
|
||||
const homeCom = await getHomeCommunity()
|
||||
if (!homeCom) {
|
||||
throw new LogError('HomeCommunity not found')
|
||||
}
|
||||
if (homeCom.gmsApiKey === null) {
|
||||
throw new LogError('HomeCommunity needs GMS-ApiKey to publish user data to GMS.')
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Community as DbCommunity, FederatedCommunity as DbFederatedCommunity } from 'database'
|
||||
import { Community as DbCommunity, FederatedCommunity as DbFederatedCommunity, getHomeCommunity } from 'database'
|
||||
import { Arg, Args, Authorized, Mutation, Query, Resolver } from 'type-graphql'
|
||||
import { IsNull, Not } from 'typeorm'
|
||||
|
||||
@ -16,7 +16,6 @@ import {
|
||||
getAllCommunities,
|
||||
getCommunityByIdentifier,
|
||||
getCommunityByUuid,
|
||||
getHomeCommunity,
|
||||
} from './util/communities'
|
||||
|
||||
@Resolver()
|
||||
|
||||
@ -21,6 +21,7 @@ import {
|
||||
Transaction as DbTransaction,
|
||||
TransactionLink as DbTransactionLink,
|
||||
User as DbUser,
|
||||
getHomeCommunity,
|
||||
} from 'database'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql'
|
||||
@ -49,7 +50,6 @@ import { executeTransaction } from './TransactionResolver'
|
||||
import {
|
||||
getAuthenticatedCommunities,
|
||||
getCommunityByUuid,
|
||||
getHomeCommunity,
|
||||
} from './util/communities'
|
||||
import { getUserCreation, validateContribution } from './util/creations'
|
||||
import { getLastTransaction } from './util/getLastTransaction'
|
||||
@ -442,6 +442,9 @@ export class TransactionLinkResolver {
|
||||
)
|
||||
// TODO:encode/sign the jwt normally with the private key of the sender/home community, but interims with uuid
|
||||
const homeCom = await getHomeCommunity()
|
||||
if (!homeCom) {
|
||||
throw new LogError('Home community not found')
|
||||
}
|
||||
if (!homeCom.communityUuid) {
|
||||
throw new LogError('Home community UUID is not set')
|
||||
}
|
||||
@ -630,6 +633,9 @@ export class TransactionLinkResolver {
|
||||
)
|
||||
}
|
||||
const homeCommunity = await getHomeCommunity()
|
||||
if (!homeCommunity) {
|
||||
throw new LogError('Home community not found')
|
||||
}
|
||||
const recipientCommunity = new Community(homeCommunity)
|
||||
const senderCommunity = new Community(senderCom)
|
||||
const senderUser = new User(null)
|
||||
|
||||
@ -93,7 +93,7 @@ import { Logger, getLogger } from 'log4js'
|
||||
import { FULL_CREATION_AVAILABLE } from './const/const'
|
||||
import { Location2Point, Point2Location } from './util/Location2Point'
|
||||
import { authenticateGmsUserPlayground } from './util/authenticateGmsUserPlayground'
|
||||
import { getHomeCommunity } from './util/communities'
|
||||
import { getHomeCommunity } from 'database'
|
||||
import { compareGmsRelevantUserSettings } from './util/compareGmsRelevantUserSettings'
|
||||
import { getUserCreations } from './util/creations'
|
||||
import { extractGraphQLFieldsForSelect } from './util/extractGraphQLFields'
|
||||
@ -381,6 +381,10 @@ export class UserResolver {
|
||||
)
|
||||
let dbUser = new DbUser()
|
||||
const homeCom = await getHomeCommunity()
|
||||
if (!homeCom) {
|
||||
logger.error('no home community found, please start the dht-node first')
|
||||
throw new Error(`Error creating user, please write the support team: ${CONFIG.COMMUNITY_SUPPORT_MAIL}`)
|
||||
}
|
||||
if (homeCom.communityUuid) {
|
||||
dbUser.communityUuid = homeCom.communityUuid
|
||||
}
|
||||
@ -821,6 +825,12 @@ export class UserResolver {
|
||||
if (CONFIG.GMS_ACTIVE && updateUserInGMS) {
|
||||
logger.debug(`changed user-settings relevant for gms-user update...`)
|
||||
const homeCom = await getHomeCommunity()
|
||||
if (!homeCom) {
|
||||
logger.error('no home community found, please start the dht-node first')
|
||||
throw new Error(
|
||||
`Error updating user, please write the support team: ${CONFIG.COMMUNITY_SUPPORT_MAIL}`
|
||||
)
|
||||
}
|
||||
if (homeCom.gmsApiKey !== null) {
|
||||
logger.debug(`send User to Gms...`)
|
||||
await sendUserToGms(user, homeCom)
|
||||
@ -863,6 +873,12 @@ export class UserResolver {
|
||||
let result = new GmsUserAuthenticationResult()
|
||||
if (context.token) {
|
||||
const homeCom = await getHomeCommunity()
|
||||
if (!homeCom) {
|
||||
logger.error("couldn't authenticate for gms, no home community found, please start the dht-node first")
|
||||
throw new Error(
|
||||
`Error authenticating for gms, please write the support team: ${CONFIG.COMMUNITY_SUPPORT_MAIL}`
|
||||
)
|
||||
}
|
||||
if (!homeCom.gmsApiKey) {
|
||||
throw new LogError('authenticateGmsUserSearch missing HomeCommunity GmsApiKey')
|
||||
}
|
||||
@ -886,6 +902,12 @@ export class UserResolver {
|
||||
const result = new UserLocationResult()
|
||||
if (context.token) {
|
||||
const homeCom = await getHomeCommunity()
|
||||
if (!homeCom) {
|
||||
logger.error("couldn't load home community location, no home community found, please start the dht-node first")
|
||||
throw new Error(
|
||||
`Error loading user location, please write the support team: ${CONFIG.COMMUNITY_SUPPORT_MAIL}`
|
||||
)
|
||||
}
|
||||
result.communityLocation = Point2Location(homeCom.location as Point)
|
||||
result.userLocation = Point2Location(dbUser.location as Point)
|
||||
logger.info('userLocation=', result)
|
||||
|
||||
@ -36,16 +36,6 @@ export async function isHomeCommunity(communityIdentifier: string): Promise<bool
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the home community, i.e., a community that is not foreign.
|
||||
* @returns A promise that resolves to the home community, or throw if no home community was found
|
||||
*/
|
||||
export async function getHomeCommunity(): Promise<DbCommunity> {
|
||||
return await DbCommunity.findOneOrFail({
|
||||
where: [{ foreign: false }],
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Check if it is needed, because currently it isn't used at all
|
||||
* Retrieves the URL of the community with the given identifier.
|
||||
|
||||
197
bun.lock
197
bun.lock
@ -172,7 +172,7 @@
|
||||
"@biomejs/biome": "2.0.0",
|
||||
"@types/node": "^17.0.21",
|
||||
"jest": "27.2.4",
|
||||
"typescript": "^4.9.5",
|
||||
"typescript": "^5.8.3",
|
||||
},
|
||||
},
|
||||
"database": {
|
||||
@ -191,17 +191,27 @@
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"source-map-support": "^0.5.21",
|
||||
"ts-mysql-migrate": "^1.0.2",
|
||||
"tsx": "^4.19.4",
|
||||
"tsx": "^4.20.3",
|
||||
"typeorm": "^0.3.22",
|
||||
"uuid": "^8.3.2",
|
||||
"wkx": "^0.5.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.0.0",
|
||||
"@swc-node/register": "^1.10.10",
|
||||
"@swc/cli": "^0.7.3",
|
||||
"@swc/core": "^1.11.24",
|
||||
"@swc/helpers": "^0.5.17",
|
||||
"@types/faker": "^5.5.9",
|
||||
"@types/geojson": "^7946.0.13",
|
||||
"@types/node": "^17.0.21",
|
||||
"@types/jest": "27.0.2",
|
||||
"@types/node": "^18.7.14",
|
||||
"jest": "27.2.4",
|
||||
"ts-jest": "27.0.5",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^4.9.5",
|
||||
"uuid": "^8.3.2",
|
||||
"vitest": "^3.2.4",
|
||||
},
|
||||
},
|
||||
"dht-node": {
|
||||
@ -393,12 +403,13 @@
|
||||
"dependencies": {
|
||||
"database": "*",
|
||||
"esbuild": "^0.25.2",
|
||||
"zod": "^3.25.20",
|
||||
"log4js": "^6.9.1",
|
||||
"zod": "^3.25.61",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
"@types/node": "^17.0.21",
|
||||
"typescript": "^4.9.5",
|
||||
"typescript": "^5.8.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -529,6 +540,12 @@
|
||||
|
||||
"@dual-bundle/import-meta-resolve": ["@dual-bundle/import-meta-resolve@4.1.0", "", {}, "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg=="],
|
||||
|
||||
"@emnapi/core": ["@emnapi/core@1.4.3", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.2", "tslib": "^2.4.0" } }, "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g=="],
|
||||
|
||||
"@emnapi/runtime": ["@emnapi/runtime@1.4.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ=="],
|
||||
|
||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.0.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA=="],
|
||||
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q=="],
|
||||
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.4", "", { "os": "android", "cpu": "arm" }, "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ=="],
|
||||
@ -745,6 +762,8 @@
|
||||
|
||||
"@napi-rs/nice-win32-x64-msvc": ["@napi-rs/nice-win32-x64-msvc@1.0.1", "", { "os": "win32", "cpu": "x64" }, "sha512-JlF+uDcatt3St2ntBG8H02F1mM45i5SF9W+bIKiReVE6wiy3o16oBP/yxt+RZ+N6LbCImJXJ6bXNO2kn9AXicg=="],
|
||||
|
||||
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.11", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.9.0" } }, "sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA=="],
|
||||
|
||||
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
||||
|
||||
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
|
||||
@ -755,6 +774,32 @@
|
||||
|
||||
"@one-ini/wasm": ["@one-ini/wasm@0.1.1", "", {}, "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw=="],
|
||||
|
||||
"@oxc-resolver/binding-darwin-arm64": ["@oxc-resolver/binding-darwin-arm64@5.3.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-hXem5ZAguS7IlSiHg/LK0tEfLj4eUo+9U6DaFwwBEGd0L0VIF9LmuiHydRyOrdnnmi9iAAFMAn/wl2cUoiuruA=="],
|
||||
|
||||
"@oxc-resolver/binding-darwin-x64": ["@oxc-resolver/binding-darwin-x64@5.3.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-wgSwfsZkRbuYCIBLxeg1bYrtKnirAy+IJF0lwfz4z08clgdNBDbfGECJe/cd0csIZPpRcvPFe8317yf31sWhtA=="],
|
||||
|
||||
"@oxc-resolver/binding-freebsd-x64": ["@oxc-resolver/binding-freebsd-x64@5.3.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kzeE2WHgcRMmWjB071RdwEV5Pwke4o0WWslCKoh8if1puvxIxfzu3o7g6P2+v77BP5qop4cri+uvLABSO0WZjg=="],
|
||||
|
||||
"@oxc-resolver/binding-linux-arm-gnueabihf": ["@oxc-resolver/binding-linux-arm-gnueabihf@5.3.0", "", { "os": "linux", "cpu": "arm" }, "sha512-I8np34yZP/XfIkZNDbw3rweqVgfjmHYpNX3xnJZWg+f4mgO9/UNWBwetSaqXeDZqvIch/aHak+q4HVrQhQKCqg=="],
|
||||
|
||||
"@oxc-resolver/binding-linux-arm64-gnu": ["@oxc-resolver/binding-linux-arm64-gnu@5.3.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-u2ndfeEUrW898eXM+qPxIN8TvTPjI90NDQBRgaxxkOfNw3xaotloeiZGz5+Yzlfxgvxr9DY9FdYkqhUhSnGhOw=="],
|
||||
|
||||
"@oxc-resolver/binding-linux-arm64-musl": ["@oxc-resolver/binding-linux-arm64-musl@5.3.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-TzbjmFkcnESGuVItQ2diKacX8vu5G0bH3BHmIlmY4OSRLyoAlrJFwGKAHmh6C9+Amfcjo2rx8vdm7swzmsGC6Q=="],
|
||||
|
||||
"@oxc-resolver/binding-linux-riscv64-gnu": ["@oxc-resolver/binding-linux-riscv64-gnu@5.3.0", "", { "os": "linux", "cpu": "none" }, "sha512-NH3pjAqh8nuN29iRuRfTY42Vn03ctoR9VE8llfoUKUfhHUjFHYOXK5VSkhjj1usG8AeuesvqrQnLptCRQVTi/Q=="],
|
||||
|
||||
"@oxc-resolver/binding-linux-s390x-gnu": ["@oxc-resolver/binding-linux-s390x-gnu@5.3.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-tuZtkK9sJYh2MC2uhol1M/8IMTB6ZQ5jmqP2+k5XNXnOb/im94Y5uV/u2lXwVyIuKHZZHtr+0d1HrOiNahoKpw=="],
|
||||
|
||||
"@oxc-resolver/binding-linux-x64-gnu": ["@oxc-resolver/binding-linux-x64-gnu@5.3.0", "", { "os": "linux", "cpu": "x64" }, "sha512-VzhPYmZCtoES/ThcPdGSmMop7JlwgqtSvlgtKCW15ByV2JKyl8kHAHnPSBfpIooXb0ehFnRdxFtL9qtAEWy01g=="],
|
||||
|
||||
"@oxc-resolver/binding-linux-x64-musl": ["@oxc-resolver/binding-linux-x64-musl@5.3.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Hi39cWzul24rGljN4Vf1lxjXzQdCrdxO5oCT7KJP4ndSlqIUODJnfnMAP1YhcnIRvNvk+5E6sZtnEmFUd/4d8Q=="],
|
||||
|
||||
"@oxc-resolver/binding-wasm32-wasi": ["@oxc-resolver/binding-wasm32-wasi@5.3.0", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.9" }, "cpu": "none" }, "sha512-ddujvHhP3chmHnSXRlkPVUeYj4/B7eLZwL4yUid+df3WCbVh6DgoT9RmllZn21AhxgKtMdekDdyVJYKFd8tl4A=="],
|
||||
|
||||
"@oxc-resolver/binding-win32-arm64-msvc": ["@oxc-resolver/binding-win32-arm64-msvc@5.3.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-j1YYPLvUkMVNKmIFQZZJ7q6Do4cI3htUnyxNLwDSBVhSohvPIK2VG+IdtOAlWZGa7v+phEZsHfNbXVwB0oPYFQ=="],
|
||||
|
||||
"@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@5.3.0", "", { "os": "win32", "cpu": "x64" }, "sha512-LT9eOPPUqfZscQRd5mc08RBeDWOQf+dnOrKnanMallTGPe6g7+rcAlFTA8SWoJbcD45PV8yArFtCmSQSpzHZmg=="],
|
||||
|
||||
"@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="],
|
||||
|
||||
"@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.1", "", { "os": "android", "cpu": "arm64" }, "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA=="],
|
||||
@ -873,6 +918,12 @@
|
||||
|
||||
"@sqltools/formatter": ["@sqltools/formatter@1.2.5", "", {}, "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw=="],
|
||||
|
||||
"@swc-node/core": ["@swc-node/core@1.13.3", "", { "peerDependencies": { "@swc/core": ">= 1.4.13", "@swc/types": ">= 0.1" } }, "sha512-OGsvXIid2Go21kiNqeTIn79jcaX4l0G93X2rAnas4LFoDyA9wAwVK7xZdm+QsKoMn5Mus2yFLCc4OtX2dD/PWA=="],
|
||||
|
||||
"@swc-node/register": ["@swc-node/register@1.10.10", "", { "dependencies": { "@swc-node/core": "^1.13.3", "@swc-node/sourcemap-support": "^0.5.1", "colorette": "^2.0.20", "debug": "^4.3.5", "oxc-resolver": "^5.0.0", "pirates": "^4.0.6", "tslib": "^2.6.3" }, "peerDependencies": { "@swc/core": ">= 1.4.13", "typescript": ">= 4.3" } }, "sha512-jYWaI2WNEKz8KZL3sExd2KVL1JMma1/J7z+9iTpv0+fRN7LGMF8VTGGuHI2bug/ztpdZU1G44FG/Kk6ElXL9CQ=="],
|
||||
|
||||
"@swc-node/sourcemap-support": ["@swc-node/sourcemap-support@0.5.1", "", { "dependencies": { "source-map-support": "^0.5.21", "tslib": "^2.6.3" } }, "sha512-JxIvIo/Hrpv0JCHSyRpetAdQ6lB27oFYhv0PKCNf1g2gUXOjpeR1exrXccRxLMuAV5WAmGFBwRnNOJqN38+qtg=="],
|
||||
|
||||
"@swc/cli": ["@swc/cli@0.7.3", "", { "dependencies": { "@swc/counter": "^0.1.3", "@xhmikosr/bin-wrapper": "^13.0.5", "commander": "^8.3.0", "fast-glob": "^3.2.5", "minimatch": "^9.0.3", "piscina": "^4.3.1", "semver": "^7.3.8", "slash": "3.0.0", "source-map": "^0.7.3" }, "peerDependencies": { "@swc/core": "^1.2.66", "chokidar": "^4.0.1" }, "optionalPeers": ["chokidar"], "bin": { "swc": "bin/swc.js", "swcx": "bin/swcx.js", "spack": "bin/spack.js" } }, "sha512-rnVXNnlURjdOuPaBIwZ3TmBA44BF/eP0j154LanlgPEYfau74ige7cpKlKkZr1IBqMOG99lAnYNxQipDWA3hdg=="],
|
||||
|
||||
"@swc/core": ["@swc/core@1.11.24", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.21" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.11.24", "@swc/core-darwin-x64": "1.11.24", "@swc/core-linux-arm-gnueabihf": "1.11.24", "@swc/core-linux-arm64-gnu": "1.11.24", "@swc/core-linux-arm64-musl": "1.11.24", "@swc/core-linux-x64-gnu": "1.11.24", "@swc/core-linux-x64-musl": "1.11.24", "@swc/core-win32-arm64-msvc": "1.11.24", "@swc/core-win32-ia32-msvc": "1.11.24", "@swc/core-win32-x64-msvc": "1.11.24" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" }, "optionalPeers": ["@swc/helpers"] }, "sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg=="],
|
||||
@ -919,6 +970,8 @@
|
||||
|
||||
"@tsconfig/node16": ["@tsconfig/node16@1.0.4", "", {}, "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA=="],
|
||||
|
||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.9.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="],
|
||||
|
||||
"@types/accepts": ["@types/accepts@1.3.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ=="],
|
||||
|
||||
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
|
||||
@ -931,6 +984,8 @@
|
||||
|
||||
"@types/body-parser": ["@types/body-parser@1.19.5", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg=="],
|
||||
|
||||
"@types/chai": ["@types/chai@5.2.2", "", { "dependencies": { "@types/deep-eql": "*" } }, "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg=="],
|
||||
|
||||
"@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="],
|
||||
|
||||
"@types/content-disposition": ["@types/content-disposition@0.5.8", "", {}, "sha512-QVSSvno3dE0MgO76pJhmv4Qyi/j0Yk9pBp0Y7TJ2Tlj+KCgJWY6qX7nnxCOLkZ3VYRSIk1WTxCvwUSdx6CCLdg=="],
|
||||
@ -939,6 +994,8 @@
|
||||
|
||||
"@types/cors": ["@types/cors@2.8.10", "", {}, "sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ=="],
|
||||
|
||||
"@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="],
|
||||
|
||||
"@types/dotenv": ["@types/dotenv@8.2.3", "", { "dependencies": { "dotenv": "*" } }, "sha512-g2FXjlDX/cYuc5CiQvyU/6kkbP1JtmGzh0obW50zD7OKeILVL0NSpPWLXVfqoAGQjom2/SLLx9zHq0KXvD6mbw=="],
|
||||
|
||||
"@types/email-templates": ["@types/email-templates@10.0.4", "", { "dependencies": { "@types/html-to-text": "*", "@types/nodemailer": "*", "juice": "^8.0.0" } }, "sha512-8O2bdGPO6RYgH2DrnFAcuV++s+8KNA5e2Erjl6UxgKRVsBH9zXu2YLrLyOBRMn2VyEYmzgF+6QQUslpVhj0y/g=="],
|
||||
@ -2551,6 +2608,8 @@
|
||||
|
||||
"own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="],
|
||||
|
||||
"oxc-resolver": ["oxc-resolver@5.3.0", "", { "optionalDependencies": { "@oxc-resolver/binding-darwin-arm64": "5.3.0", "@oxc-resolver/binding-darwin-x64": "5.3.0", "@oxc-resolver/binding-freebsd-x64": "5.3.0", "@oxc-resolver/binding-linux-arm-gnueabihf": "5.3.0", "@oxc-resolver/binding-linux-arm64-gnu": "5.3.0", "@oxc-resolver/binding-linux-arm64-musl": "5.3.0", "@oxc-resolver/binding-linux-riscv64-gnu": "5.3.0", "@oxc-resolver/binding-linux-s390x-gnu": "5.3.0", "@oxc-resolver/binding-linux-x64-gnu": "5.3.0", "@oxc-resolver/binding-linux-x64-musl": "5.3.0", "@oxc-resolver/binding-wasm32-wasi": "5.3.0", "@oxc-resolver/binding-win32-arm64-msvc": "5.3.0", "@oxc-resolver/binding-win32-x64-msvc": "5.3.0" } }, "sha512-FHqtZx0idP5QRPSNcI5g2ItmADg7fhR3XIeWg5eRMGfp44xqRpfkdvo+EX4ZceqV9bxvl0Z8vaqMqY0gYaNYNA=="],
|
||||
|
||||
"p-cancelable": ["p-cancelable@3.0.0", "", {}, "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw=="],
|
||||
|
||||
"p-event": ["p-event@4.2.0", "", { "dependencies": { "p-timeout": "^3.1.0" } }, "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ=="],
|
||||
@ -2617,7 +2676,7 @@
|
||||
|
||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||
|
||||
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
"picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
|
||||
|
||||
"pify": ["pify@4.0.1", "", {}, "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="],
|
||||
|
||||
@ -3025,7 +3084,7 @@
|
||||
|
||||
"tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],
|
||||
|
||||
"tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="],
|
||||
"tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
||||
|
||||
"tinypool": ["tinypool@1.0.2", "", {}, "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA=="],
|
||||
|
||||
@ -3077,7 +3136,7 @@
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"tsx": ["tsx@4.19.4", "", { "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q=="],
|
||||
"tsx": ["tsx@4.20.3", "", { "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ=="],
|
||||
|
||||
"tua-body-scroll-lock": ["tua-body-scroll-lock@1.5.3", "", {}, "sha512-44W12iqek41kZuTdpEUt3JTUsMx0IxfTajXWfQyMLgzsPaMYUPZLcJkwa4P0x24h5DQ3lYvDuYvphBo4+L0t4w=="],
|
||||
|
||||
@ -3439,9 +3498,9 @@
|
||||
|
||||
"@nuxt/kit/pkg-types": ["pkg-types@2.1.0", "", { "dependencies": { "confbox": "^0.2.1", "exsolve": "^1.0.1", "pathe": "^2.0.3" } }, "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A=="],
|
||||
|
||||
"@parcel/watcher/detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="],
|
||||
"@nuxt/kit/tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="],
|
||||
|
||||
"@rollup/pluginutils/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
|
||||
"@parcel/watcher/detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="],
|
||||
|
||||
"@selderee/plugin-htmlparser2/domhandler": ["domhandler@4.3.1", "", { "dependencies": { "domelementtype": "^2.2.0" } }, "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ=="],
|
||||
|
||||
@ -3509,6 +3568,8 @@
|
||||
|
||||
"ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
|
||||
|
||||
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"apollo-boost/ts-invariant": ["ts-invariant@0.4.4", "", { "dependencies": { "tslib": "^1.9.3" } }, "sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA=="],
|
||||
|
||||
"apollo-boost/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="],
|
||||
@ -3591,12 +3652,22 @@
|
||||
|
||||
"concurrently/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
||||
|
||||
"config-schema/typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||
|
||||
"css-select/domhandler": ["domhandler@4.3.1", "", { "dependencies": { "domelementtype": "^2.2.0" } }, "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ=="],
|
||||
|
||||
"css-select/domutils": ["domutils@2.8.0", "", { "dependencies": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", "domhandler": "^4.2.0" } }, "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A=="],
|
||||
|
||||
"cssstyle/rrweb-cssom": ["rrweb-cssom@0.8.0", "", {}, "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw=="],
|
||||
|
||||
"database/@swc/cli": ["@swc/cli@0.7.7", "", { "dependencies": { "@swc/counter": "^0.1.3", "@xhmikosr/bin-wrapper": "^13.0.5", "commander": "^8.3.0", "fast-glob": "^3.2.5", "minimatch": "^9.0.3", "piscina": "^4.3.1", "semver": "^7.3.8", "slash": "3.0.0", "source-map": "^0.7.3" }, "peerDependencies": { "@swc/core": "^1.2.66", "chokidar": "^4.0.1" }, "optionalPeers": ["chokidar"], "bin": { "swc": "bin/swc.js", "swcx": "bin/swcx.js", "spack": "bin/spack.js" } }, "sha512-j4yYm9bx3pxWofaJKX1BFwj/3ngUDynN4UIQ2Xd2h0h/7Gt7zkReBTpDN7g5S13mgAYxacaTHTOUsz18097E8w=="],
|
||||
|
||||
"database/@swc/core": ["@swc/core@1.12.4", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.23" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.12.4", "@swc/core-darwin-x64": "1.12.4", "@swc/core-linux-arm-gnueabihf": "1.12.4", "@swc/core-linux-arm64-gnu": "1.12.4", "@swc/core-linux-arm64-musl": "1.12.4", "@swc/core-linux-x64-gnu": "1.12.4", "@swc/core-linux-x64-musl": "1.12.4", "@swc/core-win32-arm64-msvc": "1.12.4", "@swc/core-win32-ia32-msvc": "1.12.4", "@swc/core-win32-x64-msvc": "1.12.4" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" }, "optionalPeers": ["@swc/helpers"] }, "sha512-hn30ebV4njAn0NAUM+3a0qCF+MJgqTNSrfA/hUAbC6TVjOQy2OYGQwkUvCu/V7S2+rZxrUsTpKOnZ7qqECZV9Q=="],
|
||||
|
||||
"database/@types/node": ["@types/node@18.19.96", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-PzBvgsZ7YdFs/Kng1BSW8IGv68/SPcOxYYhT7luxD7QyzIhFS1xPTpfK3K9eHBa7hVwlW+z8nN0mOd515yaduQ=="],
|
||||
|
||||
"database/vitest": ["vitest@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", "@vitest/mocker": "3.2.4", "@vitest/pretty-format": "^3.2.4", "@vitest/runner": "3.2.4", "@vitest/snapshot": "3.2.4", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.2.4", "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A=="],
|
||||
|
||||
"decompress-response/mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
|
||||
|
||||
"dht-node/@types/jest": ["@types/jest@27.5.1", "", { "dependencies": { "jest-matcher-utils": "^27.0.0", "pretty-format": "^27.0.0" } }, "sha512-fUy7YRpT+rHXto1YlL+J9rs0uLGyiqVt3ZOTQR+4ROc47yNl8WLdVLgUloBRhOxP1PZvguHl44T3H0wAWxahYQ=="],
|
||||
@ -3607,6 +3678,8 @@
|
||||
|
||||
"dht-node/ts-jest": ["ts-jest@27.1.4", "", { "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", "jest-util": "^27.0.0", "json5": "2.x", "lodash.memoize": "4.x", "make-error": "1.x", "semver": "7.x", "yargs-parser": "20.x" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", "@types/jest": "^27.0.0", "babel-jest": ">=27.0.0 <28", "jest": "^27.0.0", "typescript": ">=3.8 <5.0" }, "optionalPeers": ["@babel/core", "@types/jest", "babel-jest"], "bin": { "ts-jest": "cli.js" } }, "sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ=="],
|
||||
|
||||
"dht-node/tsx": ["tsx@4.19.4", "", { "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q=="],
|
||||
|
||||
"dht-rpc/sodium-universal": ["sodium-universal@5.0.1", "", { "dependencies": { "sodium-native": "^5.0.1" }, "peerDependencies": { "sodium-javascript": "~0.8.0" }, "optionalPeers": ["sodium-javascript"] }, "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q=="],
|
||||
|
||||
"domexception/webidl-conversions": ["webidl-conversions@5.0.0", "", {}, "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA=="],
|
||||
@ -3719,6 +3792,8 @@
|
||||
|
||||
"jest-util/@types/node": ["@types/node@18.19.96", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-PzBvgsZ7YdFs/Kng1BSW8IGv68/SPcOxYYhT7luxD7QyzIhFS1xPTpfK3K9eHBa7hVwlW+z8nN0mOd515yaduQ=="],
|
||||
|
||||
"jest-util/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"jest-watcher/@types/node": ["@types/node@18.19.96", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-PzBvgsZ7YdFs/Kng1BSW8IGv68/SPcOxYYhT7luxD7QyzIhFS1xPTpfK3K9eHBa7hVwlW+z8nN0mOd515yaduQ=="],
|
||||
|
||||
"jest-worker/@types/node": ["@types/node@18.19.96", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-PzBvgsZ7YdFs/Kng1BSW8IGv68/SPcOxYYhT7luxD7QyzIhFS1xPTpfK3K9eHBa7hVwlW+z8nN0mOd515yaduQ=="],
|
||||
@ -3741,6 +3816,8 @@
|
||||
|
||||
"mailparser/tlds": ["tlds@1.255.0", "", { "bin": { "tlds": "bin.js" } }, "sha512-tcwMRIioTcF/FcxLev8MJWxCp+GUALRhFEqbDoZrnowmKSGqPrl5pqS+Sut2m8BgJ6S4FExCSSpGffZ0Tks6Aw=="],
|
||||
|
||||
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"mlly/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||
|
||||
"multimatch/@types/minimatch": ["@types/minimatch@3.0.5", "", {}, "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ=="],
|
||||
@ -3803,6 +3880,10 @@
|
||||
|
||||
"send/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="],
|
||||
|
||||
"shared/@biomejs/biome": ["@biomejs/biome@1.9.4", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "1.9.4", "@biomejs/cli-darwin-x64": "1.9.4", "@biomejs/cli-linux-arm64": "1.9.4", "@biomejs/cli-linux-arm64-musl": "1.9.4", "@biomejs/cli-linux-x64": "1.9.4", "@biomejs/cli-linux-x64-musl": "1.9.4", "@biomejs/cli-win32-arm64": "1.9.4", "@biomejs/cli-win32-x64": "1.9.4" }, "bin": { "biome": "bin/biome" } }, "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog=="],
|
||||
|
||||
"shared/typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||
|
||||
"simple-update-notifier/semver": ["semver@7.0.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A=="],
|
||||
|
||||
"sodium-secretstream/sodium-universal": ["sodium-universal@5.0.1", "", { "dependencies": { "sodium-native": "^5.0.1" }, "peerDependencies": { "sodium-javascript": "~0.8.0" }, "optionalPeers": ["sodium-javascript"] }, "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q=="],
|
||||
@ -3855,8 +3936,6 @@
|
||||
|
||||
"test-exclude/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
"tinyglobby/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
|
||||
|
||||
"typed-rest-client/qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="],
|
||||
|
||||
"typeorm/dotenv": ["dotenv@16.5.0", "", {}, "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg=="],
|
||||
@ -3879,16 +3958,14 @@
|
||||
|
||||
"unimport/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||
|
||||
"unimport/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
|
||||
|
||||
"unimport/pkg-types": ["pkg-types@2.1.0", "", { "dependencies": { "confbox": "^0.2.1", "exsolve": "^1.0.1", "pathe": "^2.0.3" } }, "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A=="],
|
||||
|
||||
"unimport/tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="],
|
||||
|
||||
"unimport/unplugin": ["unplugin@2.3.2", "", { "dependencies": { "acorn": "^8.14.1", "picomatch": "^4.0.2", "webpack-virtual-modules": "^0.6.2" } }, "sha512-3n7YA46rROb3zSj8fFxtxC/PqoyvYQ0llwz9wtUPUutr9ig09C8gGo5CWCwHrUzlqC1LLR43kxp5vEIyH1ac1w=="],
|
||||
|
||||
"unplugin-utils/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||
|
||||
"unplugin-utils/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
|
||||
|
||||
"unplugin-vue-components/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
|
||||
|
||||
"unplugin-vue-components/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
@ -4011,6 +4088,56 @@
|
||||
|
||||
"css-select/domutils/dom-serializer": ["dom-serializer@1.4.1", "", { "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", "entities": "^2.0.0" } }, "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag=="],
|
||||
|
||||
"database/@swc/cli/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
|
||||
|
||||
"database/@swc/cli/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
"database/@swc/core/@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.12.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HihKfeitjZU2ab94Zf893sxzFryLKX0TweGsNXXOLNtkSMLw50auuYfpRM0BOL9/uXXtuCWgRIF6P030SAX5xQ=="],
|
||||
|
||||
"database/@swc/core/@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.12.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-meYCXHyYb6RDdu2N5PNAf0EelyxPBFhRcVo4kBFLuvuNb0m6EUg///VWy8MUMXq9/s9uzGS9kJVXXdRdr/d6FA=="],
|
||||
|
||||
"database/@swc/core/@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.12.4", "", { "os": "linux", "cpu": "arm" }, "sha512-szfDbf7mE8V64of0q/LSqbk+em+T+TD3uqnH40Z7Qu/aL8vi5CHgyLjWG2SLkLLpyjgkAUF6AKrupgnBYcC2NA=="],
|
||||
|
||||
"database/@swc/core/@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.12.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-n0IY76w+Scx8m3HIVRvLkoResuwsQgjDfAk9bxn99dq4leQO+mE0fkPl0Yw/1BIsPh+kxGfopIJH9zsZ1Z2YrA=="],
|
||||
|
||||
"database/@swc/core/@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.12.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-wE5jmFi5cEQyLy8WmCWmNwfKETrnzy2D8YNi/xpYWpLPWqPhcelpa6tswkfYlbsMmmOh7hQNoTba1QdGu0jvHQ=="],
|
||||
|
||||
"database/@swc/core/@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.12.4", "", { "os": "linux", "cpu": "x64" }, "sha512-6S50Xd/7ePjEwrXyHMxpKTZ+KBrgUwMA8hQPbArUOwH4S5vHBr51heL0iXbUkppn1bkSr0J0IbOove5hzn+iqQ=="],
|
||||
|
||||
"database/@swc/core/@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.12.4", "", { "os": "linux", "cpu": "x64" }, "sha512-hbYRyaHhC13vYKuGG5BrAG5fjjWEQFfQetuFp/4QKEoXDzdnabJoixxWTQACDL3m0JW32nJ+gUzsYIPtFYkwXg=="],
|
||||
|
||||
"database/@swc/core/@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.12.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-e6EbfjPL8GA/bb1lc9Omtxjlz+1ThTsAuBsy4Q3Kpbuh6B3jclg8KzxU/6t91v23wG593mieTyR5f3Pr7X3AWw=="],
|
||||
|
||||
"database/@swc/core/@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.12.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-RG2FzmllBTUf4EksANlIvLckcBrLZEA0t13LIa6L213UZKQfEuDNHezqESgoVhJMg2S/tWauitATOCFgZNSmjg=="],
|
||||
|
||||
"database/@swc/core/@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.12.4", "", { "os": "win32", "cpu": "x64" }, "sha512-oRHKnZlR83zaMeVUCmHENa4j5uNRAWbmEpjYbzRcfC45LPFNWKGWGAGERLx0u87XMUtTGqnVYxnBTHN/rzDHOw=="],
|
||||
|
||||
"database/@swc/core/@swc/types": ["@swc/types@0.1.23", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw=="],
|
||||
|
||||
"database/vitest/@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="],
|
||||
|
||||
"database/vitest/@vitest/mocker": ["@vitest/mocker@3.2.4", "", { "dependencies": { "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ=="],
|
||||
|
||||
"database/vitest/@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="],
|
||||
|
||||
"database/vitest/@vitest/runner": ["@vitest/runner@3.2.4", "", { "dependencies": { "@vitest/utils": "3.2.4", "pathe": "^2.0.3", "strip-literal": "^3.0.0" } }, "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ=="],
|
||||
|
||||
"database/vitest/@vitest/snapshot": ["@vitest/snapshot@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ=="],
|
||||
|
||||
"database/vitest/@vitest/spy": ["@vitest/spy@3.2.4", "", { "dependencies": { "tinyspy": "^4.0.3" } }, "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw=="],
|
||||
|
||||
"database/vitest/@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="],
|
||||
|
||||
"database/vitest/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
|
||||
|
||||
"database/vitest/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||
|
||||
"database/vitest/tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="],
|
||||
|
||||
"database/vitest/tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="],
|
||||
|
||||
"database/vitest/vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="],
|
||||
|
||||
"dht-rpc/sodium-universal/sodium-native": ["sodium-native@5.0.1", "", { "dependencies": { "require-addon": "^1.1.0", "which-runtime": "^1.2.1" } }, "sha512-Q305aUXc0OzK7VVRvWkeEQJQIHs6slhFwWpyqLB5iJqhpyt2lYIVu96Y6PQ7TABIlWXVF3YiWDU3xS2Snkus+g=="],
|
||||
|
||||
"editorconfig/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
|
||||
@ -4075,6 +4202,8 @@
|
||||
|
||||
"jest-worker/jest-util/@jest/types": ["@jest/types@29.6.3", "", { "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^17.0.8", "chalk": "^4.0.0" } }, "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw=="],
|
||||
|
||||
"jest-worker/jest-util/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"js-beautify/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
"jsdom/parse5/entities": ["entities@6.0.0", "", {}, "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw=="],
|
||||
@ -4111,6 +4240,22 @@
|
||||
|
||||
"send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
||||
"shared/@biomejs/biome/@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@1.9.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw=="],
|
||||
|
||||
"shared/@biomejs/biome/@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@1.9.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg=="],
|
||||
|
||||
"shared/@biomejs/biome/@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@1.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g=="],
|
||||
|
||||
"shared/@biomejs/biome/@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@1.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA=="],
|
||||
|
||||
"shared/@biomejs/biome/@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg=="],
|
||||
|
||||
"shared/@biomejs/biome/@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg=="],
|
||||
|
||||
"shared/@biomejs/biome/@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@1.9.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg=="],
|
||||
|
||||
"shared/@biomejs/biome/@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@1.9.4", "", { "os": "win32", "cpu": "x64" }, "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA=="],
|
||||
|
||||
"sodium-secretstream/sodium-universal/sodium-native": ["sodium-native@5.0.1", "", { "dependencies": { "require-addon": "^1.1.0", "which-runtime": "^1.2.1" } }, "sha512-Q305aUXc0OzK7VVRvWkeEQJQIHs6slhFwWpyqLB5iJqhpyt2lYIVu96Y6PQ7TABIlWXVF3YiWDU3xS2Snkus+g=="],
|
||||
|
||||
"streamroller/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="],
|
||||
@ -4131,8 +4276,6 @@
|
||||
|
||||
"typeorm/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
"unctx/unplugin/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
|
||||
|
||||
"unimport/pkg-types/confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="],
|
||||
|
||||
"unplugin-vue-components/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
@ -4141,6 +4284,8 @@
|
||||
|
||||
"unplugin-vue-components/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
|
||||
|
||||
"vite-plugin-html/@rollup/pluginutils/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
|
||||
|
||||
"vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
|
||||
@ -4217,6 +4362,8 @@
|
||||
|
||||
"cheerio-select/domutils/dom-serializer/entities": ["entities@2.2.0", "", {}, "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="],
|
||||
|
||||
"chokidar-cli/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"chokidar-cli/yargs/cliui/strip-ansi": ["strip-ansi@5.2.0", "", { "dependencies": { "ansi-regex": "^4.1.0" } }, "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA=="],
|
||||
|
||||
"chokidar-cli/yargs/cliui/wrap-ansi": ["wrap-ansi@5.1.0", "", { "dependencies": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", "strip-ansi": "^5.0.0" } }, "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q=="],
|
||||
@ -4233,6 +4380,14 @@
|
||||
|
||||
"css-select/domutils/dom-serializer/entities": ["entities@2.2.0", "", {}, "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="],
|
||||
|
||||
"database/@swc/cli/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
|
||||
|
||||
"database/vitest/@vitest/mocker/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
||||
|
||||
"database/vitest/@vitest/spy/tinyspy": ["tinyspy@4.0.3", "", {}, "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A=="],
|
||||
|
||||
"database/vitest/@vitest/utils/loupe": ["loupe@3.1.4", "", {}, "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg=="],
|
||||
|
||||
"editorconfig/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"filelist/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
@ -4257,6 +4412,8 @@
|
||||
|
||||
"mailparser/html-to-text/selderee/parseley": ["parseley@0.12.1", "", { "dependencies": { "leac": "^0.6.0", "peberminta": "^0.9.0" } }, "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw=="],
|
||||
|
||||
"nodemon/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"pkg-dir/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
||||
|
||||
"run-applescript/execa/cross-spawn/path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="],
|
||||
@ -4273,6 +4430,8 @@
|
||||
|
||||
"typeorm/glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
|
||||
|
||||
"unplugin-vue-components/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"unplugin-vue-components/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"vue-apollo/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||
@ -4295,6 +4454,8 @@
|
||||
|
||||
"chokidar-cli/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
|
||||
|
||||
"database/@swc/cli/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"js-beautify/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
"build:bun": "bun build src/index.ts --outdir=build --target=bun --packages=external",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"test": "bun test",
|
||||
"test:debug": "bun test --inspect-brk",
|
||||
"lint": "biome check --error-on-warnings .",
|
||||
"lint:fix": "biome check --error-on-warnings . --write"
|
||||
},
|
||||
@ -26,7 +27,7 @@
|
||||
"@biomejs/biome": "2.0.0",
|
||||
"@types/node": "^17.0.21",
|
||||
"jest": "27.2.4",
|
||||
"typescript": "^4.9.5"
|
||||
"typescript": "^5.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.2",
|
||||
|
||||
99
config-schema/test/testSetup.bun.ts
Normal file
99
config-schema/test/testSetup.bun.ts
Normal file
@ -0,0 +1,99 @@
|
||||
import { mock, jest } from 'bun:test'
|
||||
import { inspect } from 'node:util'
|
||||
/*
|
||||
* This file is used to mock the log4js logger in the tests.
|
||||
* It is used to collect all log entries in the logs array.
|
||||
* If you want to debug your test, you can use `printLogs()` to print all log entries collected through the tests.
|
||||
* To have only the relevant logs, call `clearLogs()` before your calling the methods you like to test and `printLogs()` after.
|
||||
*
|
||||
* This is the bun version
|
||||
*/
|
||||
|
||||
jest.setTimeout(1000000)
|
||||
|
||||
type LogEntry = {
|
||||
level: string;
|
||||
message: string;
|
||||
logger: string;
|
||||
context: string;
|
||||
additional: any[];
|
||||
}
|
||||
|
||||
const loggers: { [key: string]: any } = {}
|
||||
const logs: LogEntry[] = []
|
||||
|
||||
function addLog(level: string, message: string, logger: string, context: Map<string, string>, additional: any[]) {
|
||||
logs.push({
|
||||
level,
|
||||
context: [...context.entries()].map(([key, value]) => `${key}=${value}`).join(' ').trimEnd(),
|
||||
message,
|
||||
logger,
|
||||
additional
|
||||
})
|
||||
}
|
||||
|
||||
export function printLogs() {
|
||||
for (const log of logs) {
|
||||
const messages = []
|
||||
messages.push(log.message)
|
||||
// console.log('additionals: ', JSON.stringify(log.additional, null, 2))
|
||||
messages.push(log.additional.map((d) => inspect(d)).filter((d) => d))
|
||||
process.stdout.write(`${log.logger} [${log.level}] ${log.context} ${messages.join(' ')}\n`)
|
||||
}
|
||||
}
|
||||
|
||||
export function clearLogs(): void {
|
||||
logs.length = 0
|
||||
}
|
||||
|
||||
const getLoggerMocked = mock().mockImplementation((param: any) => {
|
||||
if (loggers[param]) {
|
||||
// TODO: check if it is working when tests run in parallel
|
||||
loggers[param].clearContext()
|
||||
return loggers[param]
|
||||
}
|
||||
// console.log('getLogger called with: ', param)
|
||||
const fakeLogger = {
|
||||
context: new Map<string, string>(),
|
||||
addContext: jest.fn((key: string, value: string) => {
|
||||
fakeLogger.context.set(key, value)
|
||||
}),
|
||||
trace: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('trace', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
debug: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('debug', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
warn: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('warn', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
info: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('info', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
error: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('error', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
fatal: jest.fn((message: string, ...args: any[]) => {
|
||||
addLog('fatal', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
removeContext: jest.fn((key: string) => {
|
||||
fakeLogger.context.delete(key)
|
||||
}),
|
||||
clearContext: jest.fn(() => {
|
||||
fakeLogger.context.clear()
|
||||
})
|
||||
}
|
||||
loggers[param] = fakeLogger
|
||||
return fakeLogger
|
||||
})
|
||||
|
||||
mock.module('log4js', () => ({
|
||||
getLogger: getLoggerMocked
|
||||
}))
|
||||
|
||||
export function getLogger(name: string) {
|
||||
if (!loggers[name]) {
|
||||
return getLoggerMocked(name)
|
||||
}
|
||||
return loggers[name]
|
||||
}
|
||||
@ -20,19 +20,32 @@
|
||||
"lint": "biome check --error-on-warnings .",
|
||||
"lint:fix": "biome check --error-on-warnings . --write",
|
||||
"clear": "cross-env TZ=UTC tsx migration/index.ts clear",
|
||||
"test": "cross-env TZ=UTC NODE_ENV=development DB_DATABASE=gradido_test vitest run",
|
||||
"test:debug": "cross-env TZ=UTC NODE_ENV=development DB_DATABASE=gradido_test node --inspect-brk node_modules/.bin/jest --bail --runInBand --forceExit --detectOpenHandles",
|
||||
"up": "cross-env TZ=UTC tsx migration/index.ts up",
|
||||
"down": "cross-env TZ=UTC tsx migration/index.ts down",
|
||||
"reset": "cross-env TZ=UTC tsx migration/index.ts reset",
|
||||
"up:test": "cross-env TZ=UTC DB_DATABASE=gradido_test tsx migration/index.ts up",
|
||||
"up:backend_test": "cross-env TZ=UTC DB_DATABASE=gradido_test_backend tsx migration/index.ts up",
|
||||
"up:federation_test": "cross-env TZ=UTC DB_DATABASE=gradido_test_federation tsx migration/index.ts up",
|
||||
"up:dht_test": "cross-env TZ=UTC DB_DATABASE=gradido_test_dht tsx migration/index.ts up"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.0.0",
|
||||
"@swc-node/register": "^1.10.10",
|
||||
"@swc/cli": "^0.7.3",
|
||||
"@swc/core": "^1.11.24",
|
||||
"@swc/helpers": "^0.5.17",
|
||||
"@types/faker": "^5.5.9",
|
||||
"@types/geojson": "^7946.0.13",
|
||||
"@types/node": "^17.0.21",
|
||||
"typescript": "^4.9.5"
|
||||
"@types/jest": "27.0.2",
|
||||
"@types/node": "^18.7.14",
|
||||
"jest": "27.2.4",
|
||||
"ts-jest": "27.0.5",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^4.9.5",
|
||||
"uuid": "^8.3.2",
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/uuid": "^8.3.4",
|
||||
@ -47,7 +60,7 @@
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"source-map-support": "^0.5.21",
|
||||
"ts-mysql-migrate": "^1.0.2",
|
||||
"tsx": "^4.19.4",
|
||||
"tsx": "^4.20.3",
|
||||
"typeorm": "^0.3.22",
|
||||
"uuid": "^8.3.2",
|
||||
"wkx": "^0.5.0"
|
||||
|
||||
@ -4,7 +4,7 @@ import { Migration, entities } from './entity'
|
||||
import { getLogger } from 'log4js'
|
||||
import { latestDbVersion } from '.'
|
||||
import { CONFIG } from './config'
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from './config/const'
|
||||
import { LOG4JS_BASE_CATEGORY_NAME, MIGRATIONS_TABLE } from './config/const'
|
||||
|
||||
const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.AppDatabase`)
|
||||
|
||||
@ -93,6 +93,7 @@ export class AppDatabase {
|
||||
public async destroy(): Promise<void> {
|
||||
await this.dataSource?.destroy()
|
||||
}
|
||||
|
||||
// ######################################
|
||||
// private methods
|
||||
// ######################################
|
||||
|
||||
@ -2,6 +2,10 @@ import dotenv from 'dotenv'
|
||||
|
||||
dotenv.config()
|
||||
|
||||
const defaults = {
|
||||
DEFAULT_LANGUAGE: process.env.DEFAULT_LANGUAGE ?? 'en',
|
||||
}
|
||||
|
||||
const database = {
|
||||
DB_CONNECT_RETRY_COUNT: process.env.DB_CONNECT_RETRY_COUNT
|
||||
? Number.parseInt(process.env.DB_CONNECT_RETRY_COUNT)
|
||||
@ -21,4 +25,4 @@ const database = {
|
||||
const PRODUCTION = process.env.NODE_ENV === 'production' || false
|
||||
const nodeEnv = process.env.NODE_ENV || 'development'
|
||||
|
||||
export const CONFIG = { ...database, NODE_ENV: nodeEnv, PRODUCTION }
|
||||
export const CONFIG = { ...database, NODE_ENV: nodeEnv, PRODUCTION, ...defaults }
|
||||
|
||||
@ -59,4 +59,5 @@ export const entities = [
|
||||
|
||||
export { latestDbVersion }
|
||||
export * from './logging'
|
||||
export * from './queries'
|
||||
export { AppDatabase } from './AppDatabase'
|
||||
|
||||
40
database/src/queries/communities.test.ts
Normal file
40
database/src/queries/communities.test.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { Community } from '..'
|
||||
import { AppDatabase } from '../AppDatabase'
|
||||
import { getHomeCommunity } from './communities'
|
||||
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
|
||||
import { createCommunity } from '../seeds/homeCommunity'
|
||||
|
||||
const db = AppDatabase.getInstance()
|
||||
|
||||
beforeAll(async () => {
|
||||
await db.init()
|
||||
})
|
||||
afterAll(async () => {
|
||||
await db.destroy()
|
||||
})
|
||||
|
||||
describe('community.queries', () => {
|
||||
beforeAll(async () => {
|
||||
await Community.clear()
|
||||
})
|
||||
describe('getHomeCommunity', () => {
|
||||
it('should return null if no home community exists', async () => {
|
||||
await createCommunity(true)
|
||||
expect(await getHomeCommunity()).toBeNull()
|
||||
})
|
||||
it('should return the home community', async () => {
|
||||
const homeCom = await createCommunity(false)
|
||||
const community = await getHomeCommunity()
|
||||
expect(community).toBeDefined()
|
||||
expect(community?.name).toBe(homeCom.name)
|
||||
expect(community?.description).toBe(homeCom.description)
|
||||
expect(community?.url).toBe(homeCom.url)
|
||||
expect(community?.creationDate).toStrictEqual(homeCom.creationDate)
|
||||
expect(community?.communityUuid).toBe(homeCom.communityUuid)
|
||||
expect(community?.authenticatedAt).toStrictEqual(homeCom.authenticatedAt)
|
||||
expect(community?.foreign).toBe(homeCom.foreign)
|
||||
expect(community?.publicKey).toStrictEqual(homeCom.publicKey)
|
||||
expect(community?.privateKey).toStrictEqual(homeCom.privateKey)
|
||||
})
|
||||
})
|
||||
})
|
||||
11
database/src/queries/communities.ts
Normal file
11
database/src/queries/communities.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Community as DbCommunity } from '../entity/Community'
|
||||
|
||||
/**
|
||||
* Retrieves the home community, i.e., a community that is not foreign.
|
||||
* @returns A promise that resolves to the home community, or null if no home community was found
|
||||
*/
|
||||
export async function getHomeCommunity(): Promise<DbCommunity | null> {
|
||||
return await DbCommunity.findOne({
|
||||
where: { foreign: false },
|
||||
})
|
||||
}
|
||||
2
database/src/queries/index.ts
Normal file
2
database/src/queries/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './user'
|
||||
export * from './communities'
|
||||
42
database/src/queries/user.test.ts
Normal file
42
database/src/queries/user.test.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { User, UserContact } from '..'
|
||||
import { AppDatabase } from '../AppDatabase'
|
||||
import { aliasExists } from './user'
|
||||
import { userFactory } from '../seeds/factory/user'
|
||||
import { bibiBloxberg } from '../seeds/users/bibi-bloxberg'
|
||||
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
|
||||
|
||||
const db = AppDatabase.getInstance()
|
||||
|
||||
beforeAll(async () => {
|
||||
await db.init()
|
||||
})
|
||||
afterAll(async () => {
|
||||
await db.destroy()
|
||||
})
|
||||
|
||||
describe('integration test mysql queries', () => {
|
||||
describe('user.queries', () => {
|
||||
describe('aliasExists', () => {
|
||||
beforeAll(async () => {
|
||||
await User.clear()
|
||||
await UserContact.clear()
|
||||
|
||||
const bibi = bibiBloxberg
|
||||
bibi.alias = 'b-b'
|
||||
await userFactory(bibi)
|
||||
})
|
||||
|
||||
it('should return true if alias exists', async () => {
|
||||
expect(await aliasExists('b-b')).toBe(true)
|
||||
})
|
||||
|
||||
it('should return true if alias exists even with deviating casing', async () => {
|
||||
expect(await aliasExists('b-B')).toBe(true)
|
||||
})
|
||||
|
||||
it('should return false if alias does not exist', async () => {
|
||||
expect(await aliasExists('bibi')).toBe(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
9
database/src/queries/user.ts
Normal file
9
database/src/queries/user.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { Raw } from 'typeorm'
|
||||
import { User as DbUser } from '../entity'
|
||||
|
||||
export async function aliasExists(alias: string): Promise<boolean> {
|
||||
const user = await DbUser.findOne({
|
||||
where: { alias: Raw((a) => `LOWER(${a}) = LOWER(:alias)`, { alias }) },
|
||||
})
|
||||
return user !== null
|
||||
}
|
||||
37
database/src/seeds/factory/user.ts
Normal file
37
database/src/seeds/factory/user.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { UserInterface } from '../users/UserInterface'
|
||||
import { User, UserContact } from '../../entity'
|
||||
import { generateRandomNumber, generateRandomNumericString } from '../utils'
|
||||
import { v4 } from 'uuid'
|
||||
|
||||
export const userFactory = async (user: UserInterface): Promise<User> => {
|
||||
let dbUserContact = new UserContact()
|
||||
|
||||
dbUserContact.email = user.email ?? ''
|
||||
dbUserContact.type = 'email' //UserContactType.USER_CONTACT_EMAIL
|
||||
|
||||
let dbUser = new User()
|
||||
dbUser.firstName = user.firstName ?? ''
|
||||
dbUser.lastName = user.lastName ?? ''
|
||||
dbUser.alias = user.alias ?? ''
|
||||
dbUser.language = user.language ?? 'en'
|
||||
dbUser.createdAt = user.createdAt ?? new Date()
|
||||
dbUser.deletedAt = user.deletedAt ?? null
|
||||
dbUser.publisherId = user.publisherId ?? 0
|
||||
dbUser.gradidoID = v4()
|
||||
|
||||
if (user.emailChecked) {
|
||||
dbUserContact.emailVerificationCode = generateRandomNumericString(64)
|
||||
dbUserContact.emailOptInTypeId = 1 //OptInType.EMAIL_OPT_IN_REGISTER
|
||||
dbUserContact.emailChecked = true
|
||||
dbUser.password = generateRandomNumber()
|
||||
// TODO: think where to put enums
|
||||
dbUser.passwordEncryptionType = 2 //PasswordEncryptionType.GRADIDO_ID
|
||||
}
|
||||
// TODO: improve with cascade
|
||||
dbUser = await dbUser.save()
|
||||
dbUserContact.userId = dbUser.id
|
||||
dbUserContact = await dbUserContact.save()
|
||||
dbUser.emailId = dbUserContact.id
|
||||
dbUser.emailContact = dbUserContact
|
||||
return dbUser.save()
|
||||
}
|
||||
26
database/src/seeds/homeCommunity.ts
Normal file
26
database/src/seeds/homeCommunity.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { Community } from '../entity'
|
||||
import { randomBytes } from 'node:crypto'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
export async function createCommunity(foreign: boolean): Promise<Community> {
|
||||
const homeCom = new Community()
|
||||
homeCom.publicKey = randomBytes(32)
|
||||
homeCom.communityUuid = uuidv4()
|
||||
homeCom.authenticatedAt = new Date()
|
||||
homeCom.name = 'HomeCommunity-name'
|
||||
homeCom.creationDate = new Date()
|
||||
|
||||
if(foreign) {
|
||||
homeCom.foreign = true
|
||||
homeCom.name = 'ForeignCommunity-name'
|
||||
homeCom.description = 'ForeignCommunity-description'
|
||||
homeCom.url = 'http://foreign/api'
|
||||
} else {
|
||||
homeCom.foreign = false
|
||||
homeCom.privateKey = randomBytes(64)
|
||||
homeCom.name = 'HomeCommunity-name'
|
||||
homeCom.description = 'HomeCommunity-description'
|
||||
homeCom.url = 'http://localhost/api'
|
||||
}
|
||||
return await homeCom.save()
|
||||
}
|
||||
13
database/src/seeds/users/UserInterface.ts
Normal file
13
database/src/seeds/users/UserInterface.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export interface UserInterface {
|
||||
alias?: string
|
||||
email?: string
|
||||
firstName?: string
|
||||
lastName?: string
|
||||
// description?: string
|
||||
createdAt?: Date
|
||||
emailChecked?: boolean
|
||||
language?: string
|
||||
deletedAt?: Date
|
||||
publisherId?: number
|
||||
role?: string
|
||||
}
|
||||
12
database/src/seeds/users/bibi-bloxberg.ts
Normal file
12
database/src/seeds/users/bibi-bloxberg.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { UserInterface } from './UserInterface'
|
||||
|
||||
export const bibiBloxberg: UserInterface = {
|
||||
email: 'bibi@bloxberg.de',
|
||||
firstName: 'Bibi',
|
||||
lastName: 'Bloxberg',
|
||||
alias: 'BBB',
|
||||
// description: 'Hex Hex',
|
||||
emailChecked: true,
|
||||
language: 'de',
|
||||
publisherId: 1234,
|
||||
}
|
||||
11
database/src/seeds/users/bob-baumeister.ts
Normal file
11
database/src/seeds/users/bob-baumeister.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { UserInterface } from './UserInterface'
|
||||
|
||||
export const bobBaumeister: UserInterface = {
|
||||
alias: 'MeisterBob',
|
||||
email: 'bob@baumeister.de',
|
||||
firstName: 'Bob',
|
||||
lastName: 'der Baumeister',
|
||||
// description: 'Können wir das schaffen? Ja, wir schaffen das!',
|
||||
emailChecked: true,
|
||||
language: 'de',
|
||||
}
|
||||
12
database/src/seeds/users/garrick-ollivander.ts
Normal file
12
database/src/seeds/users/garrick-ollivander.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { UserInterface } from './UserInterface'
|
||||
|
||||
export const garrickOllivander: UserInterface = {
|
||||
email: 'garrick@ollivander.com',
|
||||
firstName: 'Garrick',
|
||||
lastName: 'Ollivander',
|
||||
// description: `Curious ... curious ...
|
||||
// Renowned wandmaker Mr Ollivander owns the wand shop Ollivanders: Makers of Fine Wands Since 382 BC in Diagon Alley. His shop is widely considered the best place to purchase a wand.`,
|
||||
createdAt: new Date('2022-01-10T10:23:17'),
|
||||
emailChecked: false,
|
||||
language: 'en',
|
||||
}
|
||||
15
database/src/seeds/users/index.ts
Normal file
15
database/src/seeds/users/index.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { bibiBloxberg } from './bibi-bloxberg'
|
||||
import { bobBaumeister } from './bob-baumeister'
|
||||
import { garrickOllivander } from './garrick-ollivander'
|
||||
import { peterLustig } from './peter-lustig'
|
||||
import { raeuberHotzenplotz } from './raeuber-hotzenplotz'
|
||||
import { stephenHawking } from './stephen-hawking'
|
||||
|
||||
export const users = [
|
||||
peterLustig,
|
||||
bibiBloxberg,
|
||||
bobBaumeister,
|
||||
raeuberHotzenplotz,
|
||||
stephenHawking,
|
||||
garrickOllivander,
|
||||
]
|
||||
11
database/src/seeds/users/peter-lustig.ts
Normal file
11
database/src/seeds/users/peter-lustig.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { UserInterface } from './UserInterface'
|
||||
|
||||
export const peterLustig: UserInterface = {
|
||||
email: 'peter@lustig.de',
|
||||
firstName: 'Peter',
|
||||
lastName: 'Lustig',
|
||||
// description: 'Latzhose und Nickelbrille',
|
||||
createdAt: new Date('2020-11-25T10:48:43'),
|
||||
emailChecked: true,
|
||||
language: 'de'
|
||||
}
|
||||
10
database/src/seeds/users/raeuber-hotzenplotz.ts
Normal file
10
database/src/seeds/users/raeuber-hotzenplotz.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { UserInterface } from './UserInterface'
|
||||
|
||||
export const raeuberHotzenplotz: UserInterface = {
|
||||
email: 'raeuber@hotzenplotz.de',
|
||||
firstName: 'Räuber',
|
||||
lastName: 'Hotzenplotz',
|
||||
// description: 'Pfefferpistole',
|
||||
emailChecked: true,
|
||||
language: 'de',
|
||||
}
|
||||
12
database/src/seeds/users/stephen-hawking.ts
Normal file
12
database/src/seeds/users/stephen-hawking.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { UserInterface } from './UserInterface'
|
||||
|
||||
export const stephenHawking: UserInterface = {
|
||||
email: 'stephen@hawking.uk',
|
||||
firstName: 'Stephen',
|
||||
lastName: 'Hawking',
|
||||
// description: 'A Brief History of Time',
|
||||
emailChecked: true,
|
||||
createdAt: new Date('1942-01-08T09:17:52'),
|
||||
deletedAt: new Date('2018-03-14T09:17:52'),
|
||||
language: 'en',
|
||||
}
|
||||
10
database/src/seeds/utils.ts
Normal file
10
database/src/seeds/utils.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { randomBytes } from 'node:crypto'
|
||||
|
||||
export function generateRandomNumber(): BigInt {
|
||||
return BigInt(randomBytes(8).readBigUInt64LE())
|
||||
}
|
||||
export function generateRandomNumericString(length: number = 64): string {
|
||||
const digits = '0123456789'
|
||||
const bytes = randomBytes(length / 8)
|
||||
return Array.from(bytes, (b) => digits[b % 10]).join('').slice(0, length)
|
||||
}
|
||||
@ -50,7 +50,7 @@
|
||||
//"@/*": ["src/*"], /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
//},
|
||||
// "rootDirs": [".", "../database"], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
"typeRoots": ["node_modules/@types"], /* List of folders to include type definitions from. */
|
||||
// "types": ["node"], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
@ -71,5 +71,8 @@
|
||||
"skipLibCheck": true, /* Skip type checking of declaration files. */
|
||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||
},
|
||||
"references": [] /* Any project that is referenced must itself have a `references` array (which may be empty). */
|
||||
"references": [], /* Any project that is referenced must itself have a `references` array (which may be empty). */
|
||||
"ts-node": {
|
||||
"swc": true
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,10 +13,16 @@
|
||||
"up:dht_test": {
|
||||
"cache": false
|
||||
},
|
||||
"up:test": {
|
||||
"cache": false
|
||||
},
|
||||
"up": {
|
||||
"cache": false,
|
||||
"dependsOn": ["build"]
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": ["up:test"]
|
||||
},
|
||||
"down": {
|
||||
"cache": false,
|
||||
"dependsOn": ["build"]
|
||||
|
||||
1060
database/yarn.lock
1060
database/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@ import {
|
||||
CommunityLoggingView,
|
||||
Community as DbCommunity,
|
||||
FederatedCommunity as DbFederatedCommunity,
|
||||
getHomeCommunity,
|
||||
} from 'database'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
@ -234,7 +235,7 @@ async function writeFederatedHomeCommunityEntries(pubKey: string): Promise<Commu
|
||||
async function writeHomeCommunityEntry(keyPair: KeyPair): Promise<void> {
|
||||
try {
|
||||
// check for existing homeCommunity entry
|
||||
let homeCom = await DbCommunity.findOne({ where: { foreign: false } })
|
||||
let homeCom = await getHomeCommunity()
|
||||
if (homeCom) {
|
||||
// simply update the existing entry, but it MUST keep the ID and UUID because of possible relations
|
||||
homeCom.publicKey = keyPair.publicKey
|
||||
|
||||
@ -54,7 +54,7 @@
|
||||
"typeRoots": [ /* List of folders to include type definitions from. */
|
||||
"src/dht_node/@types",
|
||||
"node_modules/@types",
|
||||
"../node_modules/@types"
|
||||
// "../node_modules/@types"
|
||||
],
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
|
||||
2
shared/bunfig.toml
Normal file
2
shared/bunfig.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[test]
|
||||
preload = ["../config-schema/test/testSetup.bun.ts"]
|
||||
@ -17,6 +17,8 @@
|
||||
"scripts": {
|
||||
"build": "esbuild src/index.ts --outdir=build --platform=node --target=node18.20.7 --bundle --packages=external",
|
||||
"build:bun": "bun build src/index.ts --outdir=build --target=bun --packages=external",
|
||||
"test": "bun test",
|
||||
"test:debug": "bun test --inspect-brk",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"lint": "biome check --error-on-warnings .",
|
||||
"lint:fix": "biome check --error-on-warnings . --write"
|
||||
@ -24,12 +26,13 @@
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
"@types/node": "^17.0.21",
|
||||
"typescript": "^4.9.5"
|
||||
"typescript": "^5.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"database": "*",
|
||||
"esbuild": "^0.25.2",
|
||||
"zod": "^3.25.20"
|
||||
"log4js": "^6.9.1",
|
||||
"zod": "^3.25.61"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
|
||||
1
shared/src/config/const.ts
Normal file
1
shared/src/config/const.ts
Normal file
@ -0,0 +1 @@
|
||||
export const LOG4JS_BASE_CATEGORY_NAME = 'shared'
|
||||
@ -1,5 +0,0 @@
|
||||
describe('shared', () => {
|
||||
it('should be true', () => {
|
||||
expect(true).toBe(true)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,3 @@
|
||||
import * as schema from './schema'
|
||||
|
||||
export { schema }
|
||||
4
shared/src/schema/index.ts
Normal file
4
shared/src/schema/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '../config/const'
|
||||
|
||||
export const LOG_CATEGORY_SCHEMA_ALIAS = `${LOG4JS_BASE_CATEGORY_NAME}.schema`
|
||||
export * from './user.schema'
|
||||
181
shared/src/schema/user.schema.test.ts
Normal file
181
shared/src/schema/user.schema.test.ts
Normal file
@ -0,0 +1,181 @@
|
||||
import { validateAlias } from './user.schema'
|
||||
import { getLogger } from '../../../config-schema/test/testSetup.bun'
|
||||
import { LOG_CATEGORY_SCHEMA_ALIAS } from '.'
|
||||
import { describe, it, expect, beforeEach, mock, jest } from 'bun:test'
|
||||
import { aliasExists } from 'database'
|
||||
|
||||
const logger = getLogger(`${LOG_CATEGORY_SCHEMA_ALIAS}.alias`)
|
||||
|
||||
mock.module('database', () => ({
|
||||
aliasExists: jest.fn(),
|
||||
}))
|
||||
|
||||
describe('validate alias', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('alias too short', () => {
|
||||
it('throws and logs an error', () => {
|
||||
expect(validateAlias('Bi')).rejects.toThrowError(new Error('Given alias is too short'))
|
||||
expect(logger.warn.mock.calls[0]).toEqual([
|
||||
'invalid alias',
|
||||
'Bi',
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
code: 'too_small',
|
||||
minimum: 3,
|
||||
type: 'string',
|
||||
inclusive: true,
|
||||
exact: false,
|
||||
message: 'Given alias is too short',
|
||||
path: [],
|
||||
}),
|
||||
]),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('alias too long', () => {
|
||||
it('throws and logs an error', () => {
|
||||
expect(validateAlias('BibiBloxbergHexHexHex')).rejects.toThrowError(
|
||||
new Error('Given alias is too long'),
|
||||
)
|
||||
expect(logger.warn.mock.calls[0]).toEqual([
|
||||
'invalid alias',
|
||||
'BibiBloxbergHexHexHex',
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
code: 'too_big',
|
||||
maximum: 20,
|
||||
type: 'string',
|
||||
inclusive: true,
|
||||
exact: false,
|
||||
message: 'Given alias is too long',
|
||||
path: [],
|
||||
}),
|
||||
]),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('alias contains invalid characters', () => {
|
||||
it('throws and logs an error', () => {
|
||||
expect(validateAlias('Bibi.Bloxberg')).rejects.toEqual(
|
||||
new Error('Invalid characters in alias'),
|
||||
)
|
||||
expect(logger.warn.mock.calls[0]).toEqual([
|
||||
'invalid alias',
|
||||
'Bibi.Bloxberg',
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
validation: 'regex',
|
||||
code: 'invalid_string',
|
||||
message: 'Invalid characters in alias',
|
||||
path: [],
|
||||
}),
|
||||
]),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('alias is a reserved word', () => {
|
||||
it('throws and logs an error', () => {
|
||||
expect(validateAlias('admin')).rejects.toEqual(new Error('Given alias is not allowed'))
|
||||
expect(logger.warn.mock.calls[0]).toEqual([
|
||||
'invalid alias',
|
||||
'admin',
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
code: 'custom',
|
||||
message: 'Given alias is not allowed',
|
||||
path: [],
|
||||
}),
|
||||
]),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('alias is a reserved word with uppercase characters', () => {
|
||||
it('throws and logs an error', () => {
|
||||
expect(validateAlias('Admin')).rejects.toEqual(new Error('Given alias is not allowed'))
|
||||
expect(logger.warn.mock.calls[0]).toEqual([
|
||||
'invalid alias',
|
||||
'Admin',
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
code: 'custom',
|
||||
message: 'Given alias is not allowed',
|
||||
path: [],
|
||||
}),
|
||||
]),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('hyphens and underscore', () => {
|
||||
describe('alias starts with underscore', () => {
|
||||
it('throws and logs an error', () => {
|
||||
expect(validateAlias('_bibi')).rejects.toEqual(
|
||||
new Error('Invalid characters in alias'),
|
||||
)
|
||||
expect(logger.warn.mock.calls[0]).toEqual([
|
||||
'invalid alias',
|
||||
'_bibi',
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
validation: 'regex',
|
||||
code: 'invalid_string',
|
||||
message: 'Invalid characters in alias',
|
||||
path: [],
|
||||
}),
|
||||
]),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('alias contains two following hyphens', () => {
|
||||
it('throws and logs an error', () => {
|
||||
expect(validateAlias('bi--bi')).rejects.toEqual(
|
||||
new Error('Invalid characters in alias'),
|
||||
)
|
||||
expect(logger.warn.mock.calls[0]).toEqual([
|
||||
'invalid alias',
|
||||
'bi--bi',
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
validation: 'regex',
|
||||
code: 'invalid_string',
|
||||
message: 'Invalid characters in alias',
|
||||
path: [],
|
||||
}),
|
||||
]),
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
// TODO: add integration test with real database to test the query, maybe move query
|
||||
describe('test against existing alias in database', () => {
|
||||
describe('alias exists in database', () => {
|
||||
it('throws and logs an error', () => {
|
||||
(aliasExists as jest.Mock).mockResolvedValue(true)
|
||||
expect(validateAlias('b-b')).rejects.toEqual(new Error('Given alias is already in use'))
|
||||
expect(logger.warn.mock.calls[0]).toEqual(['alias already in use', 'b-b'])
|
||||
})
|
||||
})
|
||||
|
||||
/* describe('alias exists in database with in lower-case', () => {
|
||||
it('throws and logs an error', () => {
|
||||
expect(validateAlias('b-B')).rejects.toEqual(new Error('Given alias is already in use'))
|
||||
expect(logger.warn.mock.calls[0]).toEqual(['alias already in use', 'b-B'])
|
||||
})
|
||||
})
|
||||
*/
|
||||
describe('valid alias', () => {
|
||||
it('resolves to true', async () => {
|
||||
(aliasExists as jest.Mock).mockResolvedValue(false)
|
||||
expect(validateAlias('bibi')).resolves.toEqual(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
54
shared/src/schema/user.schema.ts
Normal file
54
shared/src/schema/user.schema.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { z } from 'zod'
|
||||
import { getLogger } from 'log4js'
|
||||
import { LOG_CATEGORY_SCHEMA_ALIAS } from '.'
|
||||
import { aliasExists } from 'database'
|
||||
|
||||
export const VALID_ALIAS_REGEX = /^(?=.{3,20}$)[a-zA-Z0-9]+(?:[_-][a-zA-Z0-9]+?)*$/
|
||||
const logger = getLogger(`${LOG_CATEGORY_SCHEMA_ALIAS}.alias`)
|
||||
|
||||
const RESERVED_ALIAS = [
|
||||
'admin',
|
||||
'email',
|
||||
'gast',
|
||||
'gdd',
|
||||
'gradido',
|
||||
'guest',
|
||||
'home',
|
||||
'root',
|
||||
'support',
|
||||
'temp',
|
||||
'tmp',
|
||||
'tmp',
|
||||
'user',
|
||||
'usr',
|
||||
'var',
|
||||
]
|
||||
|
||||
export const aliasSchema = z
|
||||
.string()
|
||||
.min(3, 'Given alias is too short')
|
||||
.max(20, 'Given alias is too long')
|
||||
.regex(VALID_ALIAS_REGEX, 'Invalid characters in alias')
|
||||
.refine((val) => !RESERVED_ALIAS.includes(val.toLowerCase()), {
|
||||
message: 'Given alias is not allowed',
|
||||
})
|
||||
|
||||
export const validateAlias = async (alias: string): Promise<true> => {
|
||||
try {
|
||||
aliasSchema.parse(alias)
|
||||
} catch (err) {
|
||||
if (err instanceof z.ZodError) {
|
||||
// throw only first error, but log all errors
|
||||
logger.warn('invalid alias', alias, err.errors)
|
||||
throw new Error(err.errors[0].message)
|
||||
}
|
||||
throw err
|
||||
}
|
||||
|
||||
if (await aliasExists(alias)) {
|
||||
logger.warn('alias already in use', alias)
|
||||
throw new Error('Given alias is already in use')
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
import { backendLogger as logger } from './logger'
|
||||
|
||||
export class LogError extends Error {
|
||||
constructor(msg: string, ...details: any[]) {
|
||||
super(msg)
|
||||
logger.error(msg, ...details)
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
import { readFileSync } from 'fs'
|
||||
|
||||
import { configure, getLogger } from 'log4js'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
|
||||
const options = JSON.parse(readFileSync(CONFIG.LOG4JS_CONFIG, 'utf-8'))
|
||||
|
||||
options.categories.backend.level = CONFIG.LOG_LEVEL
|
||||
options.categories.apollo.level = CONFIG.LOG_LEVEL
|
||||
|
||||
configure(options)
|
||||
|
||||
const apolloLogger = getLogger('apollo')
|
||||
const backendLogger = getLogger('backend')
|
||||
const klickTippLogger = getLogger('klicktipp')
|
||||
const gmsLogger = getLogger('gms')
|
||||
|
||||
backendLogger.addContext('user', 'unknown')
|
||||
|
||||
export { apolloLogger, backendLogger, klickTippLogger, gmsLogger }
|
||||
@ -1,97 +0,0 @@
|
||||
import { validateAlias } from './alias'
|
||||
|
||||
describe('validate alias', () => {
|
||||
beforeAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('alias too short', () => {
|
||||
it('throws and logs an error', async () => {
|
||||
await expect(validateAlias('Bi')).rejects.toEqual(new Error('Given alias is too short'))
|
||||
expect(logger.error).toBeCalledWith('Given alias is too short', 'Bi')
|
||||
})
|
||||
})
|
||||
|
||||
describe('alias too long', () => {
|
||||
it('throws and logs an error', async () => {
|
||||
await expect(validateAlias('BibiBloxbergHexHexHex')).rejects.toEqual(
|
||||
new Error('Given alias is too long'),
|
||||
)
|
||||
expect(logger.error).toBeCalledWith('Given alias is too long', 'BibiBloxbergHexHexHex')
|
||||
})
|
||||
})
|
||||
|
||||
describe('alias contains invalid characters', () => {
|
||||
it('throws and logs an error', async () => {
|
||||
await expect(validateAlias('Bibi.Bloxberg')).rejects.toEqual(
|
||||
new Error('Invalid characters in alias'),
|
||||
)
|
||||
expect(logger.error).toBeCalledWith('Invalid characters in alias', 'Bibi.Bloxberg')
|
||||
})
|
||||
})
|
||||
|
||||
describe('alias is a reserved word', () => {
|
||||
it('throws and logs an error', async () => {
|
||||
await expect(validateAlias('admin')).rejects.toEqual(new Error('Alias is not allowed'))
|
||||
expect(logger.error).toBeCalledWith('Alias is not allowed', 'admin')
|
||||
})
|
||||
})
|
||||
|
||||
describe('alias is a reserved word with uppercase characters', () => {
|
||||
it('throws and logs an error', async () => {
|
||||
await expect(validateAlias('Admin')).rejects.toEqual(new Error('Alias is not allowed'))
|
||||
expect(logger.error).toBeCalledWith('Alias is not allowed', 'Admin')
|
||||
})
|
||||
})
|
||||
|
||||
describe('hyphens and underscore', () => {
|
||||
describe('alias starts with underscore', () => {
|
||||
it('throws and logs an error', async () => {
|
||||
await expect(validateAlias('_bibi')).rejects.toEqual(
|
||||
new Error('Invalid characters in alias'),
|
||||
)
|
||||
expect(logger.error).toBeCalledWith('Invalid characters in alias', '_bibi')
|
||||
})
|
||||
})
|
||||
|
||||
describe('alias contains two following hyphens', () => {
|
||||
it('throws and logs an error', async () => {
|
||||
await expect(validateAlias('bi--bi')).rejects.toEqual(
|
||||
new Error('Invalid characters in alias'),
|
||||
)
|
||||
expect(logger.error).toBeCalledWith('Invalid characters in alias', 'bi--bi')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('test against existing alias in database', () => {
|
||||
beforeAll(async () => {
|
||||
const bibi = await userFactory(testEnv, bibiBloxberg)
|
||||
const user = await User.findOne({ where: { id: bibi.id } })
|
||||
if (user) {
|
||||
user.alias = 'b-b'
|
||||
await user.save()
|
||||
}
|
||||
})
|
||||
|
||||
describe('alias exists in database', () => {
|
||||
it('throws and logs an error', async () => {
|
||||
await expect(validateAlias('b-b')).rejects.toEqual(new Error('Alias already in use'))
|
||||
expect(logger.error).toBeCalledWith('Alias already in use', 'b-b')
|
||||
})
|
||||
})
|
||||
|
||||
describe('alias exists in database with in lower-case', () => {
|
||||
it('throws and logs an error', async () => {
|
||||
await expect(validateAlias('b-B')).rejects.toEqual(new Error('Alias already in use'))
|
||||
expect(logger.error).toBeCalledWith('Alias already in use', 'b-B')
|
||||
})
|
||||
})
|
||||
|
||||
describe('valid alias', () => {
|
||||
it('resolves to true', async () => {
|
||||
await expect(validateAlias('bibi')).resolves.toEqual(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -1,66 +0,0 @@
|
||||
import { z } from 'zod'
|
||||
import { User as DbUser } from 'database'
|
||||
import { Raw } from 'typeorm'
|
||||
// import { LogError } from '@/server/LogError'
|
||||
|
||||
class LogError extends Error {
|
||||
details: any[]
|
||||
constructor(msg: string, ...details: any[]) {
|
||||
super(msg)
|
||||
this.name = 'LogError'
|
||||
this.message = msg
|
||||
this.stack = new Error().stack
|
||||
this.details = details
|
||||
}
|
||||
}
|
||||
|
||||
export const VALID_ALIAS_REGEX = /^(?=.{3,20}$)[a-zA-Z0-9]+(?:[_-][a-zA-Z0-9]+?)*$/
|
||||
|
||||
const RESERVED_ALIAS = [
|
||||
'admin',
|
||||
'email',
|
||||
'gast',
|
||||
'gdd',
|
||||
'gradido',
|
||||
'guest',
|
||||
'home',
|
||||
'root',
|
||||
'support',
|
||||
'temp',
|
||||
'tmp',
|
||||
'tmp',
|
||||
'user',
|
||||
'usr',
|
||||
'var',
|
||||
]
|
||||
|
||||
export const aliasSchema = z
|
||||
.string()
|
||||
.min(3, 'Alias is too short')
|
||||
.max(20, 'Alias is too long')
|
||||
.regex(VALID_ALIAS_REGEX, 'Invalid characters in alias')
|
||||
.refine((val) => !RESERVED_ALIAS.includes(val.toLowerCase()), {
|
||||
message: 'Alias is not allowed',
|
||||
})
|
||||
|
||||
export const validateAlias = async (alias: string): Promise<true> => {
|
||||
try {
|
||||
aliasSchema.parse(alias)
|
||||
} catch (err) {
|
||||
if (err instanceof z.ZodError) {
|
||||
console.log(err)
|
||||
throw new LogError(err.errors[0].message, alias)
|
||||
}
|
||||
throw err
|
||||
}
|
||||
|
||||
const aliasInUse = await DbUser.find({
|
||||
where: { alias: Raw((a) => `LOWER(${a}) = "${alias.toLowerCase()}"`) },
|
||||
})
|
||||
|
||||
if (aliasInUse.length !== 0) {
|
||||
throw new LogError('Alias already in use', alias)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
|
||||
@ -49,7 +48,7 @@
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [".", "../database"], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
// "types": ["bun-types"], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
@ -69,5 +68,6 @@
|
||||
"skipLibCheck": true, /* Skip type checking of declaration files. */
|
||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||
},
|
||||
"references": [] /* Any project that is referenced must itself have a `references` array (which may be empty). */
|
||||
"references": [], /* Any project that is referenced must itself have a `references` array (which may be empty). */
|
||||
"exclude": ["**/*.test.ts", "**/*.spec.ts", "test/*", "**/bun.d.ts"],
|
||||
}
|
||||
|
||||
@ -1,16 +1,17 @@
|
||||
{
|
||||
"$schema": "https://turbo.build/schema.json",
|
||||
"extends": ["//"],
|
||||
"tasks": {
|
||||
"lint": {
|
||||
},
|
||||
"lint:fix": {
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": ["config-schema#build"]
|
||||
},
|
||||
"typecheck": {
|
||||
},
|
||||
"dev": {
|
||||
"dependsOn": ["database#build"],
|
||||
"dependsOn": ["database#build", "config-schema#build"],
|
||||
"persistent": true,
|
||||
"cache": false
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user