mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
Merge pull request #3507 from gradido/refactor_shared_module
refactor(other): add shared module
This commit is contained in:
commit
52942fa908
6
.github/file-filters.yml
vendored
6
.github/file-filters.yml
vendored
@ -36,6 +36,12 @@ backend: &backend
|
||||
config: &config
|
||||
- 'config-schema/**/*'
|
||||
|
||||
shared: &shared
|
||||
- 'shared/**/*'
|
||||
|
||||
core: &core
|
||||
- 'core/**/*'
|
||||
|
||||
database: &database
|
||||
- 'database/**/*'
|
||||
|
||||
|
||||
30
.github/workflows/lint.yml
vendored
30
.github/workflows/lint.yml
vendored
@ -7,6 +7,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
config-schema: ${{ steps.config-schema.outputs.success }}
|
||||
shared: ${{ steps.shared.outputs.success }}
|
||||
core: ${{ steps.core.outputs.success }}
|
||||
backend: ${{ steps.backend.outputs.success }}
|
||||
database: ${{ steps.database.outputs.success }}
|
||||
dht-node: ${{ steps.dht-node.outputs.success }}
|
||||
@ -25,6 +27,18 @@ jobs:
|
||||
biome ci .
|
||||
echo $?
|
||||
echo "success=$([ $? -eq 0 ] && echo true || echo false)" >> $GITHUB_OUTPUT
|
||||
- name: Lint - Shared
|
||||
id: shared
|
||||
run: |
|
||||
cd ./shared
|
||||
biome ci .
|
||||
echo "success=$([ $? -eq 0 ] && echo true || echo false)" >> $GITHUB_OUTPUT
|
||||
- name: Lint - Core
|
||||
id: core
|
||||
run: |
|
||||
cd ./core
|
||||
biome ci .
|
||||
echo "success=$([ $? -eq 0 ] && echo true || echo false)" >> $GITHUB_OUTPUT
|
||||
- name: Lint - Backend
|
||||
id: backend
|
||||
run: |
|
||||
@ -58,6 +72,22 @@ jobs:
|
||||
- name: Check result from previous step
|
||||
run: if [ "${{ needs.lint.outputs.config-schema }}" != "true" ]; then exit 1; fi
|
||||
|
||||
lint_shared:
|
||||
name: Lint - Shared
|
||||
needs: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check result from previous step
|
||||
run: if [ "${{ needs.lint.outputs.shared }}" != "true" ]; then exit 1; fi
|
||||
|
||||
lint_core:
|
||||
name: Lint - Core
|
||||
needs: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check result from previous step
|
||||
run: if [ "${{ needs.lint.outputs.core }}" != "true" ]; then exit 1; fi
|
||||
|
||||
lint_backend:
|
||||
name: Lint - Backend
|
||||
needs: lint
|
||||
|
||||
1
.github/workflows/lint_pr.yml
vendored
1
.github/workflows/lint_pr.yml
vendored
@ -35,6 +35,7 @@ jobs:
|
||||
workflow
|
||||
docker
|
||||
other
|
||||
shared
|
||||
# Configure that a scope must always be provided.
|
||||
requireScope: true
|
||||
# Configure which scopes (newline delimited) are disallowed in PR
|
||||
|
||||
10
.github/workflows/test_backend.yml
vendored
10
.github/workflows/test_backend.yml
vendored
@ -9,6 +9,8 @@ jobs:
|
||||
outputs:
|
||||
backend: ${{ steps.changes.outputs.backend }}
|
||||
config: ${{ steps.changes.outputs.config }}
|
||||
core: ${{ steps.changes.outputs.core }}
|
||||
shared: ${{ steps.changes.outputs.shared }}
|
||||
database: ${{ steps.changes.outputs.database }}
|
||||
docker-compose: ${{ steps.changes.outputs.docker-compose }}
|
||||
mariadb: ${{ steps.changes.outputs.mariadb }}
|
||||
@ -24,7 +26,7 @@ jobs:
|
||||
list-files: shell
|
||||
|
||||
build_test:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.config == 'true' || needs.files-changed.outputs.database == 'true'
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.config == 'true' || needs.files-changed.outputs.core == 'true' || needs.files-changed.outputs.database == 'true' || needs.files-changed.outputs.shared == 'true' || needs.files-changed.outputs.docker-compose == 'true'
|
||||
name: Docker Build Test - Backend
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
@ -36,7 +38,7 @@ jobs:
|
||||
run: docker build -f ./backend/Dockerfile --target production -t "gradido/backend:production" .
|
||||
|
||||
unit_test:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.database == 'true' || needs.files-changed.outputs.docker-compose == 'true' || needs.files-changed.outputs.mariadb == 'true' || needs.files-changed.outputs.config == 'true'
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.database == 'true' || needs.files-changed.outputs.docker-compose == 'true' || needs.files-changed.outputs.mariadb == 'true' || needs.files-changed.outputs.config == 'true' || needs.files-changed.outputs.core == 'true' || needs.files-changed.outputs.shared == 'true'
|
||||
name: Unit tests - Backend
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
@ -57,14 +59,14 @@ jobs:
|
||||
|
||||
- name: install dependencies
|
||||
run: |
|
||||
bun install --filter backend --frozen-lockfile
|
||||
bun install --filter backend --filter core --frozen-lockfile
|
||||
bun install --global --no-save turbo@^2
|
||||
|
||||
- name: Backend | Unit tests
|
||||
run: turbo backend#test
|
||||
|
||||
typecheck:
|
||||
if: needs.files-changed.outputs.backend == 'true'
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.core == 'true' || needs.files-changed.outputs.shared == 'true' || needs.files-changed.outputs.database == 'true' || needs.files-changed.outputs.config == 'true'
|
||||
name: Typecheck - Backend
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
43
.github/workflows/test_core.yml
vendored
Normal file
43
.github/workflows/test_core.yml
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
name: Gradido Core Test CI
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Detect File Changes - Core
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
core: ${{ steps.changes.outputs.core }}
|
||||
database: ${{ steps.changes.outputs.database }}
|
||||
shared: ${{ steps.changes.outputs.shared }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
|
||||
- name: Check for core 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 - Core
|
||||
if: needs.files-changed.outputs.core == 'true' || needs.files-changed.outputs.database == 'true' || needs.files-changed.outputs.shared == '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 core --frozen-lockfile
|
||||
bun install --global turbo@^2
|
||||
|
||||
- name: typecheck && unit test
|
||||
run: turbo core#test core#typecheck
|
||||
|
||||
11
.github/workflows/test_database.yml
vendored
11
.github/workflows/test_database.yml
vendored
@ -8,6 +8,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
database: ${{ steps.changes.outputs.database }}
|
||||
shared: ${{ steps.changes.outputs.shared }}
|
||||
docker-compose: ${{ steps.changes.outputs.docker-compose }}
|
||||
mariadb: ${{ steps.changes.outputs.mariadb }}
|
||||
steps:
|
||||
@ -22,7 +23,7 @@ jobs:
|
||||
list-files: shell
|
||||
|
||||
build:
|
||||
if: needs.files-changed.outputs.database == 'true'
|
||||
if: needs.files-changed.outputs.database == 'true' || needs.files-changed.outputs.docker-compose == 'true' || needs.files-changed.outputs.shared == 'true'
|
||||
name: Docker Build Test - Database up
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
@ -34,7 +35,7 @@ jobs:
|
||||
run: docker build --target build -t "gradido/database:build" -f database/Dockerfile .
|
||||
|
||||
database_migration_test:
|
||||
if: needs.files-changed.outputs.database == 'true' || needs.files-changed.outputs.docker-compose == 'true' || needs.files-changed.outputs.mariadb == 'true'
|
||||
if: needs.files-changed.outputs.database == 'true' || needs.files-changed.outputs.docker-compose == 'true' || needs.files-changed.outputs.mariadb == 'true' || needs.files-changed.outputs.shared == 'true'
|
||||
name: Database Migration Test - Up + Reset
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
@ -58,11 +59,11 @@ 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 database#test
|
||||
|
||||
- name: Database | reset
|
||||
run: turbo reset
|
||||
run: turbo database#reset
|
||||
|
||||
lint:
|
||||
if: needs.files-changed.outputs.database == 'true'
|
||||
|
||||
42
.github/workflows/test_shared.yml
vendored
Normal file
42
.github/workflows/test_shared.yml
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
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 }}
|
||||
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
|
||||
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 --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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -57,6 +57,7 @@
|
||||
"axios": "^0.21.1",
|
||||
"class-validator": "^0.13.1",
|
||||
"config-schema": "*",
|
||||
"core": "*",
|
||||
"cors": "^2.8.5",
|
||||
"database": "*",
|
||||
"decimal.js-light": "^2.5.1",
|
||||
@ -65,7 +66,7 @@
|
||||
"express": "^4.17.21",
|
||||
"express-slow-down": "^2.0.1",
|
||||
"faker": "^5.5.3",
|
||||
"graphql": "^15.10.1",
|
||||
"graphql": "15.10.1",
|
||||
"graphql-parse-resolve-info": "^4.13.1",
|
||||
"graphql-request": "5.0.0",
|
||||
"graphql-tag": "^2.12.6",
|
||||
@ -88,13 +89,14 @@
|
||||
"random-bigint": "^0.0.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"regenerator-runtime": "^0.14.1",
|
||||
"shared": "*",
|
||||
"source-map-support": "^0.5.21",
|
||||
"ts-jest": "27.0.5",
|
||||
"ts-jest": "29.4.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsconfig-paths": "^4.1.1",
|
||||
"type-graphql": "^1.1.1",
|
||||
"typed-rest-client": "^1.8.11",
|
||||
"typeorm": "^0.3.22",
|
||||
"typeorm": "^0.3.25",
|
||||
"typescript": "^4.9.5",
|
||||
"uuid": "^8.3.2",
|
||||
"workerpool": "^9.2.0",
|
||||
|
||||
@ -5,11 +5,10 @@ import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
// 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_BASE_CATEGORY_NAME}.apis.gms.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.')
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import { ApolloServerTestClient } from 'apollo-server-testing'
|
||||
import { FederatedCommunity as DbFederatedCommunity } from 'database'
|
||||
import { GraphQLClient } from 'graphql-request'
|
||||
import { Response } from 'graphql-request/dist/types'
|
||||
import { DataSource } from 'typeorm'
|
||||
import { DataSource, Not } from 'typeorm'
|
||||
|
||||
import { cleanDB, testEnvironment } from '@test/helpers'
|
||||
import { getLogger } from 'config-schema/test/testSetup'
|
||||
@ -203,7 +203,7 @@ describe('validate Communities', () => {
|
||||
overwrite: ['end_point', 'last_announced_at'],
|
||||
})
|
||||
.execute()
|
||||
await DbFederatedCommunity.update({}, { verifiedAt: null })
|
||||
await DbFederatedCommunity.update({ id: Not(0) }, { verifiedAt: null })
|
||||
// jest.clearAllMocks()
|
||||
await validateCommunities()
|
||||
})
|
||||
@ -270,7 +270,7 @@ describe('validate Communities', () => {
|
||||
})
|
||||
.execute()
|
||||
|
||||
await DbFederatedCommunity.update({}, { verifiedAt: null })
|
||||
await DbFederatedCommunity.update({ id: Not(0) }, { verifiedAt: null })
|
||||
// jest.clearAllMocks()
|
||||
await validateCommunities()
|
||||
})
|
||||
@ -322,7 +322,7 @@ describe('validate Communities', () => {
|
||||
dbCom = await DbFederatedCommunity.findOneOrFail({
|
||||
where: { publicKey: variables3.publicKey, apiVersion: variables3.apiVersion },
|
||||
})
|
||||
await DbFederatedCommunity.update({}, { verifiedAt: null })
|
||||
await DbFederatedCommunity.update({ id: Not(0) }, { verifiedAt: null })
|
||||
// jest.clearAllMocks()
|
||||
await validateCommunities()
|
||||
})
|
||||
|
||||
@ -1,14 +1,6 @@
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
|
||||
interface DecayInterface {
|
||||
balance: Decimal
|
||||
decay: Decimal
|
||||
roundedDecay: Decimal
|
||||
start: Date | null
|
||||
end: Date | null
|
||||
duration: number | null
|
||||
}
|
||||
import { Decay as DecayInterface } from 'shared'
|
||||
|
||||
@ObjectType()
|
||||
export class Decay {
|
||||
|
||||
@ -9,7 +9,7 @@ import { RIGHTS } from '@/auth/RIGHTS'
|
||||
import { BalanceLoggingView } from '@/logging/BalanceLogging.view'
|
||||
import { DecayLoggingView } from '@/logging/DecayLogging.view'
|
||||
import { Context, getUser } from '@/server/context'
|
||||
import { calculateDecay } from '@/util/decay'
|
||||
import { calculateDecay } from 'shared'
|
||||
|
||||
import { getLogger } from 'log4js'
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -19,7 +19,6 @@ import { ContributionType } from '@enum/ContributionType'
|
||||
import { TransactionTypeId } from '@enum/TransactionTypeId'
|
||||
import { AdminUpdateContribution } from '@model/AdminUpdateContribution'
|
||||
import { Contribution, ContributionListResult } from '@model/Contribution'
|
||||
import { Decay } from '@model/Decay'
|
||||
import { OpenCreation } from '@model/OpenCreation'
|
||||
import { UnconfirmedContribution } from '@model/UnconfirmedContribution'
|
||||
|
||||
@ -44,7 +43,7 @@ import { UpdateUnconfirmedContributionContext } from '@/interactions/updateUncon
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { Context, getClientTimezoneOffset, getUser } from '@/server/context'
|
||||
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
|
||||
import { calculateDecay } from '@/util/decay'
|
||||
import { calculateDecay, Decay } from 'shared'
|
||||
import { fullName } from '@/util/utilities'
|
||||
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
|
||||
@ -5,7 +5,7 @@ import { Authorized, FieldResolver, Query, Resolver } from 'type-graphql'
|
||||
import { CommunityStatistics, DynamicStatisticsFields } from '@model/CommunityStatistics'
|
||||
|
||||
import { RIGHTS } from '@/auth/RIGHTS'
|
||||
import { calculateDecay } from '@/util/decay'
|
||||
import { calculateDecay } from 'shared'
|
||||
|
||||
const db = AppDatabase.getInstance()
|
||||
|
||||
|
||||
@ -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'
|
||||
@ -38,7 +39,7 @@ import { LogError } from '@/server/LogError'
|
||||
import { Context, getClientTimezoneOffset, getUser } from '@/server/context'
|
||||
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
|
||||
import { TRANSACTION_LINK_LOCK } from '@/util/TRANSACTION_LINK_LOCK'
|
||||
import { calculateDecay } from '@/util/decay'
|
||||
import { calculateDecay } from 'shared'
|
||||
import { fullName } from '@/util/utilities'
|
||||
import { calculateBalance } from '@/util/validate'
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -137,19 +137,11 @@ describe('send coins', () => {
|
||||
}),
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
errors: [new GraphQLError('No user with this credentials')],
|
||||
errors: [new GraphQLError('The recipient user was not found')],
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('logs the error thrown', () => {
|
||||
expect(logger.error).toBeCalledWith(
|
||||
'No user with this credentials',
|
||||
'wrong@email.com',
|
||||
homeCom.communityUuid,
|
||||
)
|
||||
})
|
||||
|
||||
describe('deleted recipient', () => {
|
||||
it('throws an error', async () => {
|
||||
jest.clearAllMocks()
|
||||
@ -170,18 +162,10 @@ describe('send coins', () => {
|
||||
}),
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
errors: [new GraphQLError('No user with this credentials')],
|
||||
errors: [new GraphQLError('The recipient user was not found')],
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('logs the error thrown', () => {
|
||||
expect(logger.error).toBeCalledWith(
|
||||
'No user with this credentials',
|
||||
'stephen@hawking.uk',
|
||||
homeCom.communityUuid,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('recipient account not activated', () => {
|
||||
@ -204,18 +188,10 @@ describe('send coins', () => {
|
||||
}),
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
errors: [new GraphQLError('No user with this credentials')],
|
||||
errors: [new GraphQLError('The recipient user was not found')],
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('logs the error thrown', () => {
|
||||
expect(logger.error).toBeCalledWith(
|
||||
'No user with this credentials',
|
||||
'garrick@ollivander.com',
|
||||
homeCom.communityUuid,
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
Transaction as dbTransaction,
|
||||
TransactionLink as dbTransactionLink,
|
||||
User as dbUser,
|
||||
findUserByIdentifier
|
||||
} from 'database'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import { Args, Authorized, Ctx, Mutation, Query, Resolver } from 'type-graphql'
|
||||
@ -40,7 +41,6 @@ import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
import { BalanceResolver } from './BalanceResolver'
|
||||
import { GdtResolver } from './GdtResolver'
|
||||
import { getCommunityByIdentifier, getCommunityName, isHomeCommunity } from './util/communities'
|
||||
import { findUserByIdentifier } from './util/findUserByIdentifier'
|
||||
import { getLastTransaction } from './util/getLastTransaction'
|
||||
import { getTransactionList } from './util/getTransactionList'
|
||||
import {
|
||||
|
||||
@ -2693,166 +2693,6 @@ describe('UserResolver', () => {
|
||||
expect(logErrorLogger.error).toBeCalledWith('401 Unauthorized')
|
||||
})
|
||||
})
|
||||
|
||||
describe('authenticated', () => {
|
||||
const uuid = uuidv4()
|
||||
|
||||
beforeAll(async () => {
|
||||
user = await userFactory(testEnv, bibiBloxberg)
|
||||
await mutate({
|
||||
mutation: login,
|
||||
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||
})
|
||||
// first set alias to null, because updating alias isn't currently allowed
|
||||
await User.update({ alias: 'BBB' }, { alias: () => 'NULL' })
|
||||
await mutate({
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
alias: 'bibi',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
describe('identifier is no gradido ID, no email and no alias', () => {
|
||||
it('throws and logs "Unknown identifier type" error', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: userQuery,
|
||||
variables: {
|
||||
identifier: 'identifier_is_no_valid_alias!',
|
||||
communityIdentifier: homeCom1.communityUuid,
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
errors: [new GraphQLError('Unknown identifier type')],
|
||||
}),
|
||||
)
|
||||
expect(logErrorLogger.error).toBeCalledWith(
|
||||
'Unknown identifier type',
|
||||
'identifier_is_no_valid_alias!',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('identifier is not found', () => {
|
||||
it('throws and logs "No user found to given identifier" error', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: userQuery,
|
||||
variables: {
|
||||
identifier: uuid,
|
||||
communityIdentifier: homeCom1.communityUuid,
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
errors: [new GraphQLError('No user found to given identifier(s)')],
|
||||
}),
|
||||
)
|
||||
expect(logErrorLogger.error).toBeCalledWith(
|
||||
'No user found to given identifier(s)',
|
||||
uuid,
|
||||
homeCom1.communityUuid,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('identifier is found via email, but not matching community', () => {
|
||||
it('returns user', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: userQuery,
|
||||
variables: {
|
||||
identifier: 'bibi@bloxberg.de',
|
||||
communityIdentifier: foreignCom1.communityUuid,
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
errors: [new GraphQLError('No user with this credentials')],
|
||||
}),
|
||||
)
|
||||
expect(logErrorLogger.error).toBeCalledWith(
|
||||
'No user with this credentials',
|
||||
'bibi@bloxberg.de',
|
||||
foreignCom1.communityUuid,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('identifier is found via email', () => {
|
||||
it('returns user', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: userQuery,
|
||||
variables: {
|
||||
identifier: 'bibi@bloxberg.de',
|
||||
communityIdentifier: homeCom1.communityUuid,
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
data: {
|
||||
user: expect.objectContaining({
|
||||
firstName: 'Bibi',
|
||||
lastName: 'Bloxberg',
|
||||
}),
|
||||
},
|
||||
errors: undefined,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('identifier is found via gradidoID', () => {
|
||||
it('returns user', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: userQuery,
|
||||
variables: {
|
||||
identifier: user.gradidoID,
|
||||
communityIdentifier: homeCom1.communityUuid,
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
data: {
|
||||
user: expect.objectContaining({
|
||||
firstName: 'Bibi',
|
||||
lastName: 'Bloxberg',
|
||||
}),
|
||||
},
|
||||
errors: undefined,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('identifier is found via alias', () => {
|
||||
it('returns user', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: userQuery,
|
||||
variables: {
|
||||
identifier: 'bibi',
|
||||
communityIdentifier: homeCom1.communityUuid,
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
data: {
|
||||
user: expect.objectContaining({
|
||||
firstName: 'Bibi',
|
||||
lastName: 'Bloxberg',
|
||||
}),
|
||||
},
|
||||
errors: undefined,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('check username', () => {
|
||||
|
||||
@ -6,6 +6,8 @@ import {
|
||||
UserContact as DbUserContact,
|
||||
ProjectBranding,
|
||||
UserLoggingView,
|
||||
getHomeCommunity,
|
||||
findUserByIdentifier
|
||||
} from 'database'
|
||||
import { GraphQLResolveInfo } from 'graphql'
|
||||
import i18n from 'i18n'
|
||||
@ -93,17 +95,15 @@ 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 { compareGmsRelevantUserSettings } from './util/compareGmsRelevantUserSettings'
|
||||
import { getUserCreations } from './util/creations'
|
||||
import { extractGraphQLFieldsForSelect } from './util/extractGraphQLFields'
|
||||
import { findUserByIdentifier } from './util/findUserByIdentifier'
|
||||
import { findUsers } from './util/findUsers'
|
||||
import { getKlicktippState } from './util/getKlicktippState'
|
||||
import { deleteUserRole, setUserRole } from './util/modifyUserRole'
|
||||
import { sendUserToGms } from './util/sendUserToGms'
|
||||
import { syncHumhub } from './util/syncHumhub'
|
||||
import { validateAlias } from './util/validateAlias'
|
||||
import { validateAlias } from 'core'
|
||||
|
||||
const LANGUAGES = ['de', 'en', 'es', 'fr', 'nl']
|
||||
const DEFAULT_LANGUAGE = 'de'
|
||||
@ -380,6 +380,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
|
||||
}
|
||||
@ -820,6 +824,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)
|
||||
@ -862,6 +872,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')
|
||||
}
|
||||
@ -885,6 +901,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)
|
||||
@ -1130,8 +1152,11 @@ export class UserResolver {
|
||||
{ identifier, communityIdentifier }: UserArgs,
|
||||
): Promise<User> {
|
||||
const foundDbUser = await findUserByIdentifier(identifier, communityIdentifier)
|
||||
const modelUser = new User(foundDbUser)
|
||||
return modelUser
|
||||
if (!foundDbUser) {
|
||||
createLogger().debug('User not found', identifier, communityIdentifier)
|
||||
throw new Error('User not found')
|
||||
}
|
||||
return new User(foundDbUser)
|
||||
}
|
||||
|
||||
// FIELD RESOLVERS
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -1,65 +0,0 @@
|
||||
import { isURL } from 'class-validator'
|
||||
import { Community, User as DbUser, UserContact as DbUserContact } from 'database'
|
||||
import { FindOptionsWhere } from 'typeorm'
|
||||
import { validate, version } from 'uuid'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { isEMail, isUUID4 } from '@/util/validate'
|
||||
|
||||
import { VALID_ALIAS_REGEX } from './validateAlias'
|
||||
|
||||
/**
|
||||
*
|
||||
* @param identifier could be gradidoID, alias or email of user
|
||||
* @param communityIdentifier could be uuid or name of community
|
||||
* @returns
|
||||
*/
|
||||
export const findUserByIdentifier = async (
|
||||
identifier: string,
|
||||
communityIdentifier: string,
|
||||
): Promise<DbUser> => {
|
||||
let user: DbUser | null
|
||||
const communityWhere: FindOptionsWhere<Community> = isURL(communityIdentifier)
|
||||
? { url: communityIdentifier }
|
||||
: isUUID4(communityIdentifier)
|
||||
? { communityUuid: communityIdentifier }
|
||||
: { name: communityIdentifier }
|
||||
|
||||
if (validate(identifier) && version(identifier) === 4) {
|
||||
user = await DbUser.findOne({
|
||||
where: { gradidoID: identifier, community: communityWhere },
|
||||
relations: ['emailContact', 'community'],
|
||||
})
|
||||
if (!user) {
|
||||
throw new LogError('No user found to given identifier(s)', identifier, communityIdentifier)
|
||||
}
|
||||
} else if (isEMail(identifier)) {
|
||||
const userContact = await DbUserContact.findOne({
|
||||
where: {
|
||||
email: identifier,
|
||||
emailChecked: true,
|
||||
user: {
|
||||
community: communityWhere,
|
||||
},
|
||||
},
|
||||
relations: { user: { community: true } },
|
||||
})
|
||||
if (!userContact) {
|
||||
throw new LogError('No user with this credentials', identifier, communityIdentifier)
|
||||
}
|
||||
user = userContact.user
|
||||
user.emailContact = userContact
|
||||
} else if (VALID_ALIAS_REGEX.exec(identifier)) {
|
||||
user = await DbUser.findOne({
|
||||
where: { alias: identifier, community: communityWhere },
|
||||
relations: ['emailContact', 'community'],
|
||||
})
|
||||
if (!user) {
|
||||
throw new LogError('No user found to given identifier(s)', identifier, communityIdentifier)
|
||||
}
|
||||
} else {
|
||||
throw new LogError('Unknown identifier type', identifier)
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
@ -1,92 +0,0 @@
|
||||
import { ApolloServerTestClient } from 'apollo-server-testing'
|
||||
import { Community as DbCommunity, User as DbUser } from 'database'
|
||||
import { DataSource } from 'typeorm'
|
||||
|
||||
import { cleanDB, testEnvironment } from '@test/helpers'
|
||||
|
||||
import { writeHomeCommunityEntry } from '@/seeds/community'
|
||||
import { userFactory } from '@/seeds/factory/user'
|
||||
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
|
||||
import { bobBaumeister } from '@/seeds/users/bob-baumeister'
|
||||
import { peterLustig } from '@/seeds/users/peter-lustig'
|
||||
|
||||
import { findUserByIdentifier } from './findUserByIdentifier'
|
||||
|
||||
jest.mock('@/password/EncryptorUtils')
|
||||
|
||||
let con: DataSource
|
||||
let testEnv: {
|
||||
mutate: ApolloServerTestClient['mutate']
|
||||
query: ApolloServerTestClient['query']
|
||||
con: DataSource
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
testEnv = await testEnvironment()
|
||||
con = testEnv.con
|
||||
await cleanDB()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await cleanDB()
|
||||
await con.destroy()
|
||||
})
|
||||
|
||||
describe('graphql/resolver/util/findUserByIdentifier', () => {
|
||||
let homeCom: DbCommunity
|
||||
let communityUuid: string
|
||||
let communityName: string
|
||||
let userBibi: DbUser
|
||||
|
||||
beforeAll(async () => {
|
||||
homeCom = await writeHomeCommunityEntry()
|
||||
|
||||
communityUuid = homeCom.communityUuid!
|
||||
|
||||
communityName = homeCom.communityUuid!
|
||||
|
||||
userBibi = await userFactory(testEnv, bibiBloxberg)
|
||||
await userFactory(testEnv, peterLustig)
|
||||
await userFactory(testEnv, bobBaumeister)
|
||||
})
|
||||
|
||||
describe('communityIdentifier is community uuid', () => {
|
||||
it('userIdentifier is gradido id', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.gradidoID, communityUuid)
|
||||
user.userRoles = []
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
|
||||
it('userIdentifier is alias', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.alias, communityUuid)
|
||||
user.userRoles = []
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
|
||||
it('userIdentifier is email', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.emailContact.email, communityUuid)
|
||||
user.userRoles = []
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
})
|
||||
|
||||
describe('communityIdentifier is community name', () => {
|
||||
it('userIdentifier is gradido id', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.gradidoID, communityName)
|
||||
user.userRoles = []
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
|
||||
it('userIdentifier is alias', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.alias, communityName)
|
||||
user.userRoles = []
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
|
||||
it('userIdentifier is email', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.emailContact.email, communityName)
|
||||
user.userRoles = []
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -1,129 +0,0 @@
|
||||
import { ApolloServerTestClient } from 'apollo-server-testing'
|
||||
import { User } from 'database'
|
||||
import { DataSource } from 'typeorm'
|
||||
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
import { cleanDB, testEnvironment } from '@test/helpers'
|
||||
import { i18n as localization } from '@test/testSetup'
|
||||
import { getLogger } from 'config-schema/test/testSetup'
|
||||
|
||||
import { userFactory } from '@/seeds/factory/user'
|
||||
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
|
||||
|
||||
import { validateAlias } from './validateAlias'
|
||||
|
||||
const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.server.LogError`)
|
||||
|
||||
let con: DataSource
|
||||
let testEnv: {
|
||||
mutate: ApolloServerTestClient['mutate']
|
||||
query: ApolloServerTestClient['query']
|
||||
con: DataSource
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
testEnv = await testEnvironment(getLogger('apollo'), localization)
|
||||
con = testEnv.con
|
||||
await cleanDB()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await cleanDB()
|
||||
await con.destroy()
|
||||
})
|
||||
|
||||
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,46 +0,0 @@
|
||||
import { User as DbUser } from 'database'
|
||||
import { Raw } from 'typeorm'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
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 validateAlias = async (alias: string): Promise<boolean> => {
|
||||
if (alias.length < 3) {
|
||||
throw new LogError('Given alias is too short', alias)
|
||||
}
|
||||
if (alias.length > 20) {
|
||||
throw new LogError('Given alias is too long', alias)
|
||||
}
|
||||
if (!alias.match(VALID_ALIAS_REGEX)) {
|
||||
throw new LogError('Invalid characters in alias', alias)
|
||||
}
|
||||
if (RESERVED_ALIAS.includes(alias.toLowerCase())) {
|
||||
throw new LogError('Alias is not allowed', alias)
|
||||
}
|
||||
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,9 +1,10 @@
|
||||
import { AbstractLoggingView } from 'database'
|
||||
|
||||
import { Decay } from '@/graphql/model/Decay'
|
||||
import type { Decay as DecayInterface } from 'shared'
|
||||
|
||||
export class DecayLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: Decay) {
|
||||
public constructor(private self: Decay | DecayInterface) {
|
||||
super()
|
||||
}
|
||||
|
||||
|
||||
@ -37,7 +37,9 @@ const context = {
|
||||
export const cleanDB = async () => {
|
||||
// this only works as long we do not have foreign key constraints
|
||||
for (const entity of entities) {
|
||||
await resetEntity(entity)
|
||||
if (entity.name !== 'Migration') {
|
||||
await resetEntity(entity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import { Decay } from '@model/Decay'
|
||||
|
||||
import { getLastTransaction } from '@/graphql/resolver/util/getLastTransaction'
|
||||
|
||||
import { calculateDecay } from './decay'
|
||||
import { calculateDecay } from 'shared'
|
||||
|
||||
export async function calculateSenderBalance(
|
||||
userId: number,
|
||||
@ -16,7 +16,7 @@ export async function calculateSenderBalance(
|
||||
return null
|
||||
}
|
||||
|
||||
const decay = calculateDecay(lastTransaction.balance, lastTransaction.balanceDate, time)
|
||||
const decay = new Decay(calculateDecay(lastTransaction.balance, lastTransaction.balanceDate, time))
|
||||
|
||||
const balance = decay.balance.add(amount.toString())
|
||||
return { balance, lastTransactionId: lastTransaction.id, decay }
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { calculateDecay, decayFormula } from './decay'
|
||||
|
||||
describe('utils/decay', () => {
|
||||
describe('decayFormula', () => {
|
||||
it('has base 0.99999997802044727', () => {
|
||||
const amount = new Decimal(1.0)
|
||||
const seconds = 1
|
||||
// TODO: toString() was required, we could not compare two decimals
|
||||
expect(decayFormula(amount, seconds).toString()).toBe('0.999999978035040489732012')
|
||||
})
|
||||
it('has correct backward calculation', () => {
|
||||
const amount = new Decimal(1.0)
|
||||
const seconds = -1
|
||||
expect(decayFormula(amount, seconds).toString()).toBe('1.000000021964959992727444')
|
||||
})
|
||||
// we get pretty close, but not exact here, skipping
|
||||
|
||||
it.skip('has correct forward calculation', () => {
|
||||
const amount = new Decimal(1.0).div(
|
||||
new Decimal('0.99999997803504048973201202316767079413460520837376'),
|
||||
)
|
||||
const seconds = 1
|
||||
expect(decayFormula(amount, seconds).toString()).toBe('1.0')
|
||||
})
|
||||
})
|
||||
it('has base 0.99999997802044727', () => {
|
||||
const now = new Date()
|
||||
now.setSeconds(1)
|
||||
const oneSecondAgo = new Date(now.getTime())
|
||||
oneSecondAgo.setSeconds(0)
|
||||
expect(calculateDecay(new Decimal(1.0), oneSecondAgo, now).balance.toString()).toBe(
|
||||
'0.999999978035040489732012',
|
||||
)
|
||||
})
|
||||
|
||||
it('returns input amount when from and to is the same', () => {
|
||||
const now = new Date()
|
||||
expect(calculateDecay(new Decimal(100.0), now, now).balance.toString()).toBe('100')
|
||||
})
|
||||
})
|
||||
@ -1,71 +0,0 @@
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Decay } from '@model/Decay'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { DECAY_START_TIME } from 'config-schema'
|
||||
|
||||
Decimal.set({
|
||||
precision: 25,
|
||||
rounding: Decimal.ROUND_HALF_UP,
|
||||
})
|
||||
|
||||
// TODO: externalize all those definitions and functions into an external decay library
|
||||
|
||||
function decayFormula(value: Decimal, seconds: number): Decimal {
|
||||
// TODO why do we need to convert this here to a stting to work properly?
|
||||
return value.mul(
|
||||
new Decimal('0.99999997803504048973201202316767079413460520837376').pow(seconds).toString(),
|
||||
)
|
||||
}
|
||||
|
||||
function calculateDecay(
|
||||
amount: Decimal,
|
||||
from: Date,
|
||||
to: Date,
|
||||
startBlock: Date = DECAY_START_TIME,
|
||||
): Decay {
|
||||
const fromMs = from.getTime()
|
||||
const toMs = to.getTime()
|
||||
const startBlockMs = startBlock.getTime()
|
||||
|
||||
if (toMs < fromMs) {
|
||||
throw new LogError('calculateDecay: to < from, reverse decay calculation is invalid')
|
||||
}
|
||||
|
||||
// Initialize with no decay
|
||||
const decay: Decay = {
|
||||
balance: amount,
|
||||
decay: new Decimal(0),
|
||||
roundedDecay: new Decimal(0),
|
||||
start: null,
|
||||
end: null,
|
||||
duration: null,
|
||||
}
|
||||
|
||||
// decay started after end date; no decay
|
||||
if (startBlockMs > toMs) {
|
||||
return decay
|
||||
}
|
||||
// decay started before start date; decay for full duration
|
||||
if (startBlockMs < fromMs) {
|
||||
decay.start = from
|
||||
decay.duration = (toMs - fromMs) / 1000
|
||||
}
|
||||
// decay started between start and end date; decay from decay start till end date
|
||||
else {
|
||||
decay.start = startBlock
|
||||
decay.duration = (toMs - startBlockMs) / 1000
|
||||
}
|
||||
|
||||
decay.end = to
|
||||
decay.balance = decayFormula(amount, decay.duration)
|
||||
decay.decay = decay.balance.minus(amount)
|
||||
decay.roundedDecay = amount
|
||||
.toDecimalPlaces(2, Decimal.ROUND_DOWN)
|
||||
.minus(decay.balance.toDecimalPlaces(2, Decimal.ROUND_DOWN).toString())
|
||||
.mul(-1)
|
||||
return decay
|
||||
}
|
||||
|
||||
export { decayFormula, calculateDecay }
|
||||
@ -7,7 +7,7 @@ import { Decay } from '@model/Decay'
|
||||
import { getLastTransaction } from '@/graphql/resolver/util/getLastTransaction'
|
||||
import { transactionLinkSummary } from '@/graphql/resolver/util/transactionLinkSummary'
|
||||
|
||||
import { calculateDecay } from './decay'
|
||||
import { calculateDecay } from 'shared'
|
||||
|
||||
function isStringBoolean(value: string): boolean {
|
||||
const lowerValue = value.toLowerCase()
|
||||
@ -36,7 +36,7 @@ async function calculateBalance(
|
||||
return null
|
||||
}
|
||||
|
||||
const decay = calculateDecay(lastTransaction.balance, lastTransaction.balanceDate, time)
|
||||
const decay = new Decay(calculateDecay(lastTransaction.balance, lastTransaction.balanceDate, time))
|
||||
|
||||
const balance = decay.balance.add(amount.toString())
|
||||
const { sumHoldAvailableAmount } = await transactionLinkSummary(userId, time)
|
||||
|
||||
@ -6,7 +6,7 @@ import { TransactionTypeId } from '@enum/TransactionTypeId'
|
||||
import { Transaction } from '@model/Transaction'
|
||||
import { User } from '@model/User'
|
||||
|
||||
import { calculateDecay } from './decay'
|
||||
import { calculateDecay } from 'shared'
|
||||
|
||||
const defaultModelFunctions = {
|
||||
hasId: function (): boolean {
|
||||
|
||||
@ -23,7 +23,9 @@ const context = {
|
||||
export const cleanDB = async () => {
|
||||
// this only works as long we do not have foreign key constraints
|
||||
for (const entity of entities) {
|
||||
await resetEntity(entity)
|
||||
if (entity.name !== 'Migration') {
|
||||
await resetEntity(entity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,25 +2,22 @@
|
||||
"extends": ["//"],
|
||||
"tasks": {
|
||||
"seed": {
|
||||
"dependsOn": ["database#up", "config-schema#build", "database#build"],
|
||||
"dependsOn": ["database#up", "^build"],
|
||||
"cache": false
|
||||
},
|
||||
"locales": {},
|
||||
"locales:fix": {},
|
||||
"lint": {
|
||||
"dependsOn": ["locales", "database#build"]
|
||||
"dependsOn": ["locales"]
|
||||
},
|
||||
"lint:fix": {
|
||||
"dependsOn": ["locales:fix", "database#build"]
|
||||
},
|
||||
"typecheck": {
|
||||
"dependsOn": ["database#build", "config-schema#build"]
|
||||
"dependsOn": ["locales:fix"]
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": ["database#up:backend_test", "config-schema#build", "database#build"]
|
||||
"dependsOn": ["database#up:backend_test", "^build"]
|
||||
},
|
||||
"dev": {
|
||||
"dependsOn": ["database#up"]
|
||||
"dependsOn": ["database#up", "^build"]
|
||||
},
|
||||
"start": {
|
||||
"dependsOn": ["database#up", "build"]
|
||||
|
||||
254
bun.lock
254
bun.lock
@ -112,16 +112,17 @@
|
||||
"await-semaphore": "^0.1.3",
|
||||
"axios": "^0.21.1",
|
||||
"class-validator": "^0.13.1",
|
||||
"config-schema": "*",
|
||||
"config-schema": "workspace:*",
|
||||
"core": "workspace:*",
|
||||
"cors": "^2.8.5",
|
||||
"database": "*",
|
||||
"database": "workspace:*",
|
||||
"decimal.js-light": "^2.5.1",
|
||||
"dotenv": "^10.0.0",
|
||||
"esbuild": "^0.25.2",
|
||||
"express": "^4.17.21",
|
||||
"express-slow-down": "^2.0.1",
|
||||
"faker": "^5.5.3",
|
||||
"graphql": "^15.10.1",
|
||||
"graphql": "15.10.1",
|
||||
"graphql-parse-resolve-info": "^4.13.1",
|
||||
"graphql-request": "5.0.0",
|
||||
"graphql-tag": "^2.12.6",
|
||||
@ -144,13 +145,14 @@
|
||||
"random-bigint": "^0.0.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"regenerator-runtime": "^0.14.1",
|
||||
"shared": "workspace:*",
|
||||
"source-map-support": "^0.5.21",
|
||||
"ts-jest": "27.0.5",
|
||||
"ts-jest": "29.4.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsconfig-paths": "^4.1.1",
|
||||
"type-graphql": "^1.1.1",
|
||||
"typed-rest-client": "^1.8.11",
|
||||
"typeorm": "^0.3.22",
|
||||
"typeorm": "^0.3.25",
|
||||
"typescript": "^4.9.5",
|
||||
"uuid": "^8.3.2",
|
||||
"workerpool": "^9.2.0",
|
||||
@ -159,7 +161,7 @@
|
||||
},
|
||||
"config-schema": {
|
||||
"name": "config-schema",
|
||||
"version": "1.0.0",
|
||||
"version": "2.6.0",
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.2",
|
||||
"joi": "^17.13.3",
|
||||
@ -175,6 +177,21 @@
|
||||
"typescript": "^4.9.5",
|
||||
},
|
||||
},
|
||||
"core": {
|
||||
"name": "core",
|
||||
"version": "2.6.0",
|
||||
"dependencies": {
|
||||
"database": "*",
|
||||
"esbuild": "^0.25.2",
|
||||
"log4js": "^6.9.1",
|
||||
"zod": "^3.25.61",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.0.0",
|
||||
"@types/node": "^17.0.21",
|
||||
"typescript": "^4.9.5",
|
||||
},
|
||||
},
|
||||
"database": {
|
||||
"name": "database",
|
||||
"version": "2.6.0",
|
||||
@ -189,19 +206,30 @@
|
||||
"log4js": "^6.9.1",
|
||||
"mysql2": "^2.3.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"shared": "*",
|
||||
"source-map-support": "^0.5.21",
|
||||
"ts-mysql-migrate": "^1.0.2",
|
||||
"tsx": "^4.19.4",
|
||||
"typeorm": "^0.3.22",
|
||||
"tsx": "^4.20.3",
|
||||
"typeorm": "^0.3.25",
|
||||
"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",
|
||||
"crypto-random-bigint": "^2.1.1",
|
||||
"jest": "27.2.4",
|
||||
"ts-jest": "27.0.5",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^4.9.5",
|
||||
"vitest": "^3.2.4",
|
||||
},
|
||||
},
|
||||
"dht-node": {
|
||||
@ -235,8 +263,9 @@
|
||||
"prettier": "^2.8.8",
|
||||
"source-map-support": "^0.5.21",
|
||||
"ts-jest": "27.1.4",
|
||||
"tsconfig-paths": "^4.1.1",
|
||||
"tsx": "^4.19.4",
|
||||
"typeorm": "^0.3.22",
|
||||
"typeorm": "^0.3.25",
|
||||
"typescript": "^4.9.5",
|
||||
"uuid": "^8.3.2",
|
||||
},
|
||||
@ -287,7 +316,7 @@
|
||||
"ts-jest": "27.0.5",
|
||||
"tsconfig-paths": "^4.1.1",
|
||||
"type-graphql": "^1.1.1",
|
||||
"typeorm": "^0.3.22",
|
||||
"typeorm": "^0.3.25",
|
||||
"typescript": "^4.9.5",
|
||||
"uuid": "8.3.2",
|
||||
},
|
||||
@ -387,6 +416,23 @@
|
||||
"webpack": "^5",
|
||||
},
|
||||
},
|
||||
"shared": {
|
||||
"name": "shared",
|
||||
"version": "2.6.0",
|
||||
"dependencies": {
|
||||
"decimal.js-light": "^2.5.1",
|
||||
"esbuild": "^0.25.2",
|
||||
"log4js": "^6.9.1",
|
||||
"zod": "^3.25.61",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.0.0",
|
||||
"@types/node": "^17.0.21",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"typescript": "^4.9.5",
|
||||
"uuid": "^8.3.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="],
|
||||
@ -515,6 +561,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=="],
|
||||
@ -731,6 +783,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=="],
|
||||
@ -741,6 +795,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=="],
|
||||
@ -859,29 +939,35 @@
|
||||
|
||||
"@sqltools/formatter": ["@sqltools/formatter@1.2.5", "", {}, "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw=="],
|
||||
|
||||
"@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-node/core": ["@swc-node/core@1.13.3", "", { "peerDependencies": { "@swc/core": ">= 1.4.13", "@swc/types": ">= 0.1" } }, "sha512-OGsvXIid2Go21kiNqeTIn79jcaX4l0G93X2rAnas4LFoDyA9wAwVK7xZdm+QsKoMn5Mus2yFLCc4OtX2dD/PWA=="],
|
||||
|
||||
"@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=="],
|
||||
"@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/core-darwin-arm64": ["@swc/core-darwin-arm64@1.11.24", "", { "os": "darwin", "cpu": "arm64" }, "sha512-dhtVj0PC1APOF4fl5qT2neGjRLgHAAYfiVP8poJelhzhB/318bO+QCFWAiimcDoyMgpCXOhTp757gnoJJrheWA=="],
|
||||
"@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/core-darwin-x64": ["@swc/core-darwin-x64@1.11.24", "", { "os": "darwin", "cpu": "x64" }, "sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ=="],
|
||||
"@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=="],
|
||||
|
||||
"@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.11.24", "", { "os": "linux", "cpu": "arm" }, "sha512-PHJgWEpCsLo/NGj+A2lXZ2mgGjsr96ULNW3+T3Bj2KTc8XtMUkE8tmY2Da20ItZOvPNC/69KroU7edyo1Flfbw=="],
|
||||
"@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=="],
|
||||
|
||||
"@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.11.24", "", { "os": "linux", "cpu": "arm64" }, "sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg=="],
|
||||
"@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.12.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HihKfeitjZU2ab94Zf893sxzFryLKX0TweGsNXXOLNtkSMLw50auuYfpRM0BOL9/uXXtuCWgRIF6P030SAX5xQ=="],
|
||||
|
||||
"@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.11.24", "", { "os": "linux", "cpu": "arm64" }, "sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw=="],
|
||||
"@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.12.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-meYCXHyYb6RDdu2N5PNAf0EelyxPBFhRcVo4kBFLuvuNb0m6EUg///VWy8MUMXq9/s9uzGS9kJVXXdRdr/d6FA=="],
|
||||
|
||||
"@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.11.24", "", { "os": "linux", "cpu": "x64" }, "sha512-IM7d+STVZD48zxcgo69L0yYptfhaaE9cMZ+9OoMxirNafhKKXwoZuufol1+alEFKc+Wbwp+aUPe/DeWC/Lh3dg=="],
|
||||
"@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.12.4", "", { "os": "linux", "cpu": "arm" }, "sha512-szfDbf7mE8V64of0q/LSqbk+em+T+TD3uqnH40Z7Qu/aL8vi5CHgyLjWG2SLkLLpyjgkAUF6AKrupgnBYcC2NA=="],
|
||||
|
||||
"@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.11.24", "", { "os": "linux", "cpu": "x64" }, "sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw=="],
|
||||
"@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.12.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-n0IY76w+Scx8m3HIVRvLkoResuwsQgjDfAk9bxn99dq4leQO+mE0fkPl0Yw/1BIsPh+kxGfopIJH9zsZ1Z2YrA=="],
|
||||
|
||||
"@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.11.24", "", { "os": "win32", "cpu": "arm64" }, "sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ=="],
|
||||
"@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.12.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-wE5jmFi5cEQyLy8WmCWmNwfKETrnzy2D8YNi/xpYWpLPWqPhcelpa6tswkfYlbsMmmOh7hQNoTba1QdGu0jvHQ=="],
|
||||
|
||||
"@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.11.24", "", { "os": "win32", "cpu": "ia32" }, "sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ=="],
|
||||
"@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.12.4", "", { "os": "linux", "cpu": "x64" }, "sha512-6S50Xd/7ePjEwrXyHMxpKTZ+KBrgUwMA8hQPbArUOwH4S5vHBr51heL0iXbUkppn1bkSr0J0IbOove5hzn+iqQ=="],
|
||||
|
||||
"@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.11.24", "", { "os": "win32", "cpu": "x64" }, "sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w=="],
|
||||
"@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.12.4", "", { "os": "linux", "cpu": "x64" }, "sha512-hbYRyaHhC13vYKuGG5BrAG5fjjWEQFfQetuFp/4QKEoXDzdnabJoixxWTQACDL3m0JW32nJ+gUzsYIPtFYkwXg=="],
|
||||
|
||||
"@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.12.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-e6EbfjPL8GA/bb1lc9Omtxjlz+1ThTsAuBsy4Q3Kpbuh6B3jclg8KzxU/6t91v23wG593mieTyR5f3Pr7X3AWw=="],
|
||||
|
||||
"@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.12.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-RG2FzmllBTUf4EksANlIvLckcBrLZEA0t13LIa6L213UZKQfEuDNHezqESgoVhJMg2S/tWauitATOCFgZNSmjg=="],
|
||||
|
||||
"@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.12.4", "", { "os": "win32", "cpu": "x64" }, "sha512-oRHKnZlR83zaMeVUCmHENa4j5uNRAWbmEpjYbzRcfC45LPFNWKGWGAGERLx0u87XMUtTGqnVYxnBTHN/rzDHOw=="],
|
||||
|
||||
"@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="],
|
||||
|
||||
@ -889,7 +975,7 @@
|
||||
|
||||
"@swc/jest": ["@swc/jest@0.2.38", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@swc/counter": "^0.1.3", "jsonc-parser": "^3.2.0" }, "peerDependencies": { "@swc/core": "*" } }, "sha512-HMoZgXWMqChJwffdDjvplH53g9G2ALQes3HKXDEdliB/b85OQ0CTSbxG8VSeCwiAn7cOaDVEt4mwmZvbHcS52w=="],
|
||||
|
||||
"@swc/types": ["@swc/types@0.1.21", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ=="],
|
||||
"@swc/types": ["@swc/types@0.1.23", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw=="],
|
||||
|
||||
"@szmarczak/http-timer": ["@szmarczak/http-timer@5.0.1", "", { "dependencies": { "defer-to-connect": "^2.0.1" } }, "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw=="],
|
||||
|
||||
@ -905,6 +991,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=="],
|
||||
@ -917,6 +1005,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=="],
|
||||
@ -925,6 +1015,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=="],
|
||||
@ -1499,6 +1591,8 @@
|
||||
|
||||
"copy-anything": ["copy-anything@3.0.5", "", { "dependencies": { "is-what": "^4.1.8" } }, "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w=="],
|
||||
|
||||
"core": ["core@workspace:core"],
|
||||
|
||||
"core-js-pure": ["core-js-pure@3.42.0", "", {}, "sha512-007bM04u91fF4kMgwom2I5cQxAFIy8jVulgr9eozILl/SZE53QOqnW/+vviC+wQWLv+AunBG+8Q0TLoeSsSxRQ=="],
|
||||
|
||||
"core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="],
|
||||
@ -1515,6 +1609,8 @@
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||
|
||||
"crypto-random-bigint": ["crypto-random-bigint@2.1.1", "", { "dependencies": { "uint-rng": "^1.2.1" } }, "sha512-96+FDrenXybkpnLML/60S8NcG32KgJ5Y8yvNNCYPW02r+ssoXFR5XKenuIQcHLWumnGj8UPqUUHBzXNrDGkDmQ=="],
|
||||
|
||||
"css-functions-list": ["css-functions-list@3.2.3", "", {}, "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA=="],
|
||||
|
||||
"css-select": ["css-select@4.3.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.0.1", "domhandler": "^4.3.1", "domutils": "^2.8.0", "nth-check": "^2.0.1" } }, "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ=="],
|
||||
@ -1563,7 +1659,7 @@
|
||||
|
||||
"decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],
|
||||
|
||||
"dedent": ["dedent@0.7.0", "", {}, "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA=="],
|
||||
"dedent": ["dedent@1.6.0", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA=="],
|
||||
|
||||
"deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="],
|
||||
|
||||
@ -2537,6 +2633,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=="],
|
||||
@ -2603,7 +2701,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=="],
|
||||
|
||||
@ -2841,6 +2939,8 @@
|
||||
|
||||
"sha.js": ["sha.js@2.4.11", "", { "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" }, "bin": { "sha.js": "./bin.js" } }, "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ=="],
|
||||
|
||||
"shared": ["shared@workspace:shared"],
|
||||
|
||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
@ -3005,11 +3105,13 @@
|
||||
|
||||
"tiny-case": ["tiny-case@1.0.3", "", {}, "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q=="],
|
||||
|
||||
"tiny-webcrypto": ["tiny-webcrypto@1.0.3", "", {}, "sha512-LQQdNMAgz9BXNT2SKbYh3eCb+fLV0p7JB7MwUjzY6IOlQLGIadfnFqRpshERsS5Dl2OM/hs0+4I/XmSrF+RBbw=="],
|
||||
|
||||
"tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
|
||||
|
||||
"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=="],
|
||||
|
||||
@ -3051,7 +3153,7 @@
|
||||
|
||||
"ts-invariant": ["ts-invariant@0.10.3", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ=="],
|
||||
|
||||
"ts-jest": ["ts-jest@27.0.5", "", { "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", "jest-util": "^27.0.0", "json5": "2.x", "lodash": "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-lIJApzfTaSSbtlksfFNHkWOzLJuuSm4faFAfo5kvzOiRAuoN4/eKxVJ2zEAho8aecE04qX6K1pAzfH5QHL1/8w=="],
|
||||
"ts-jest": ["ts-jest@29.4.0", "", { "dependencies": { "bs-logger": "^0.2.6", "ejs": "^3.1.10", "fast-json-stable-stringify": "^2.1.0", "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", "semver": "^7.7.2", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", "@jest/transform": "^29.0.0 || ^30.0.0", "@jest/types": "^29.0.0 || ^30.0.0", "babel-jest": "^29.0.0 || ^30.0.0", "jest": "^29.0.0 || ^30.0.0", "jest-util": "^29.0.0 || ^30.0.0", "typescript": ">=4.3 <6" }, "optionalPeers": ["@babel/core", "@jest/transform", "@jest/types", "babel-jest", "jest-util"], "bin": { "ts-jest": "cli.js" } }, "sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q=="],
|
||||
|
||||
"ts-mysql-migrate": ["ts-mysql-migrate@1.1.2", "", { "dependencies": { "@types/mysql": "^2.15.8", "mysql": "^2.18.1" }, "bin": { "generate-migration": "dist/generate-migration.js" } }, "sha512-jwhVaMrYBNNhAoZ5XISxzqbnXTHqwazqu/r1UQ6kUaGNPGL43ZFnBiXVj4Gm3pfe3xtCGIaNInehDfdDuigPgw=="],
|
||||
|
||||
@ -3061,7 +3163,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=="],
|
||||
|
||||
@ -3103,7 +3205,7 @@
|
||||
|
||||
"typedarray-to-buffer": ["typedarray-to-buffer@3.1.5", "", { "dependencies": { "is-typedarray": "^1.0.0" } }, "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q=="],
|
||||
|
||||
"typeorm": ["typeorm@0.3.22", "", { "dependencies": { "@sqltools/formatter": "^1.2.5", "ansis": "^3.17.0", "app-root-path": "^3.1.0", "buffer": "^6.0.3", "dayjs": "^1.11.13", "debug": "^4.4.0", "dotenv": "^16.4.7", "glob": "^10.4.5", "sha.js": "^2.4.11", "sql-highlight": "^6.0.0", "tslib": "^2.8.1", "uuid": "^11.1.0", "yargs": "^17.7.2" }, "peerDependencies": { "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0", "@sap/hana-client": "^2.12.25", "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", "hdb-pool": "^0.1.6", "ioredis": "^5.0.4", "mongodb": "^5.8.0 || ^6.0.0", "mssql": "^9.1.1 || ^10.0.1 || ^11.0.1", "mysql2": "^2.2.5 || ^3.0.1", "oracledb": "^6.3.0", "pg": "^8.5.1", "pg-native": "^3.0.0", "pg-query-stream": "^4.0.0", "redis": "^3.1.1 || ^4.0.0", "reflect-metadata": "^0.1.14 || ^0.2.0", "sql.js": "^1.4.0", "sqlite3": "^5.0.3", "ts-node": "^10.7.0", "typeorm-aurora-data-api-driver": "^2.0.0 || ^3.0.0" }, "optionalPeers": ["@google-cloud/spanner", "@sap/hana-client", "better-sqlite3", "hdb-pool", "ioredis", "mongodb", "mssql", "mysql2", "oracledb", "pg", "pg-native", "pg-query-stream", "redis", "sql.js", "sqlite3", "ts-node", "typeorm-aurora-data-api-driver"], "bin": { "typeorm": "cli.js", "typeorm-ts-node-esm": "cli-ts-node-esm.js", "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js" } }, "sha512-P/Tsz3UpJ9+K0oryC0twK5PO27zejLYYwMsE8SISfZc1lVHX+ajigiOyWsKbuXpEFMjD9z7UjLzY3+ElVOMMDA=="],
|
||||
"typeorm": ["typeorm@0.3.25", "", { "dependencies": { "@sqltools/formatter": "^1.2.5", "ansis": "^3.17.0", "app-root-path": "^3.1.0", "buffer": "^6.0.3", "dayjs": "^1.11.13", "debug": "^4.4.0", "dedent": "^1.6.0", "dotenv": "^16.4.7", "glob": "^10.4.5", "sha.js": "^2.4.11", "sql-highlight": "^6.0.0", "tslib": "^2.8.1", "uuid": "^11.1.0", "yargs": "^17.7.2" }, "peerDependencies": { "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0", "@sap/hana-client": "^2.12.25", "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", "hdb-pool": "^0.1.6", "ioredis": "^5.0.4", "mongodb": "^5.8.0 || ^6.0.0", "mssql": "^9.1.1 || ^10.0.1 || ^11.0.1", "mysql2": "^2.2.5 || ^3.0.1", "oracledb": "^6.3.0", "pg": "^8.5.1", "pg-native": "^3.0.0", "pg-query-stream": "^4.0.0", "redis": "^3.1.1 || ^4.0.0", "reflect-metadata": "^0.1.14 || ^0.2.0", "sql.js": "^1.4.0", "sqlite3": "^5.0.3", "ts-node": "^10.7.0", "typeorm-aurora-data-api-driver": "^2.0.0 || ^3.0.0" }, "optionalPeers": ["@google-cloud/spanner", "@sap/hana-client", "better-sqlite3", "hdb-pool", "ioredis", "mongodb", "mssql", "mysql2", "oracledb", "pg", "pg-native", "pg-query-stream", "redis", "sql.js", "sqlite3", "ts-node", "typeorm-aurora-data-api-driver"], "bin": { "typeorm": "cli.js", "typeorm-ts-node-esm": "cli-ts-node-esm.js", "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js" } }, "sha512-fTKDFzWXKwAaBdEMU4k661seZewbNYET4r1J/z3Jwf+eAvlzMVpTLKAVcAzg75WwQk7GDmtsmkZ5MfkmXCiFWg=="],
|
||||
|
||||
"typescript": ["typescript@4.9.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g=="],
|
||||
|
||||
@ -3115,6 +3217,8 @@
|
||||
|
||||
"uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="],
|
||||
|
||||
"uint-rng": ["uint-rng@1.2.1", "", { "dependencies": { "tiny-webcrypto": "^1.0.2" } }, "sha512-swhDg5H+3DX2sIvnYA7VMBMXV/t8mPxvh49CjCDkwFmj/3OZIDOQwJANBgM1MPSUBrUHNIlXmU7/GcL7m4907g=="],
|
||||
|
||||
"uint8array-extras": ["uint8array-extras@1.4.0", "", {}, "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ=="],
|
||||
|
||||
"unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
|
||||
@ -3301,7 +3405,7 @@
|
||||
|
||||
"yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
|
||||
|
||||
"yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="],
|
||||
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
|
||||
|
||||
"yauzl": ["yauzl@3.2.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "pend": "~1.2.0" } }, "sha512-Ow9nuGZE+qp1u4JIPvg+uCiUr7xGQWdff7JQSk5VGYTAZMDe2q8lxJ10ygv10qmSj031Ty/6FNJpLO4o1Sgc+w=="],
|
||||
|
||||
@ -3423,9 +3527,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=="],
|
||||
|
||||
@ -3493,6 +3597,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=="],
|
||||
@ -3581,6 +3687,12 @@
|
||||
|
||||
"cssstyle/rrweb-cssom": ["rrweb-cssom@0.8.0", "", {}, "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw=="],
|
||||
|
||||
"database/@types/node": ["@types/node@18.19.96", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-PzBvgsZ7YdFs/Kng1BSW8IGv68/SPcOxYYhT7luxD7QyzIhFS1xPTpfK3K9eHBa7hVwlW+z8nN0mOd515yaduQ=="],
|
||||
|
||||
"database/ts-jest": ["ts-jest@27.0.5", "", { "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", "jest-util": "^27.0.0", "json5": "2.x", "lodash": "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-lIJApzfTaSSbtlksfFNHkWOzLJuuSm4faFAfo5kvzOiRAuoN4/eKxVJ2zEAho8aecE04qX6K1pAzfH5QHL1/8w=="],
|
||||
|
||||
"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=="],
|
||||
@ -3633,6 +3745,8 @@
|
||||
|
||||
"federation/helmet": ["helmet@7.2.0", "", {}, "sha512-ZRiwvN089JfMXokizgqEPXsl2Guk094yExfoDXR0cBYWxtBbaSww/w+vT4WEJsBW2iTUi1GgZ6swmoug3Oy4Xw=="],
|
||||
|
||||
"federation/ts-jest": ["ts-jest@27.0.5", "", { "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", "jest-util": "^27.0.0", "json5": "2.x", "lodash": "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-lIJApzfTaSSbtlksfFNHkWOzLJuuSm4faFAfo5kvzOiRAuoN4/eKxVJ2zEAho8aecE04qX6K1pAzfH5QHL1/8w=="],
|
||||
|
||||
"file-type/get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="],
|
||||
|
||||
"filelist/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
|
||||
@ -3677,6 +3791,8 @@
|
||||
|
||||
"jest-circus/@types/node": ["@types/node@18.19.96", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-PzBvgsZ7YdFs/Kng1BSW8IGv68/SPcOxYYhT7luxD7QyzIhFS1xPTpfK3K9eHBa7hVwlW+z8nN0mOd515yaduQ=="],
|
||||
|
||||
"jest-circus/dedent": ["dedent@0.7.0", "", {}, "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA=="],
|
||||
|
||||
"jest-cli/yargs": ["yargs@16.2.0", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw=="],
|
||||
|
||||
"jest-environment-jsdom/@types/node": ["@types/node@18.19.96", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-PzBvgsZ7YdFs/Kng1BSW8IGv68/SPcOxYYhT7luxD7QyzIhFS1xPTpfK3K9eHBa7hVwlW+z8nN0mOd515yaduQ=="],
|
||||
@ -3703,6 +3819,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=="],
|
||||
@ -3725,6 +3843,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=="],
|
||||
@ -3787,6 +3907,8 @@
|
||||
|
||||
"send/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="],
|
||||
|
||||
"shared/@types/uuid": ["@types/uuid@10.0.0", "", {}, "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ=="],
|
||||
|
||||
"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=="],
|
||||
@ -3839,10 +3961,16 @@
|
||||
|
||||
"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=="],
|
||||
"ts-jest/jest": ["jest@27.5.1", "", { "dependencies": { "@jest/core": "^27.5.1", "import-local": "^3.0.2", "jest-cli": "^27.5.1" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"], "bin": { "jest": "bin/jest.js" } }, "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ=="],
|
||||
|
||||
"ts-jest/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||
|
||||
"ts-jest/type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
|
||||
|
||||
"typed-rest-client/qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="],
|
||||
|
||||
"typeorm/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
|
||||
|
||||
"typeorm/dotenv": ["dotenv@16.5.0", "", {}, "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg=="],
|
||||
|
||||
"typeorm/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
||||
@ -3863,16 +3991,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=="],
|
||||
@ -3909,8 +4035,6 @@
|
||||
|
||||
"xss/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
|
||||
|
||||
"yargs/yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
|
||||
|
||||
"@apollographql/graphql-upload-8-fork/http-errors/depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="],
|
||||
|
||||
"@apollographql/graphql-upload-8-fork/http-errors/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="],
|
||||
@ -3995,6 +4119,34 @@
|
||||
|
||||
"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/ts-jest/yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="],
|
||||
|
||||
"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-node/ts-jest/yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="],
|
||||
|
||||
"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=="],
|
||||
@ -4005,6 +4157,8 @@
|
||||
|
||||
"express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
||||
"federation/ts-jest/yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="],
|
||||
|
||||
"file-type/get-stream/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="],
|
||||
|
||||
"filelist/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
|
||||
@ -4023,6 +4177,8 @@
|
||||
|
||||
"jest-cli/yargs/cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="],
|
||||
|
||||
"jest-cli/yargs/yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/cssstyle": ["cssstyle@2.3.0", "", { "dependencies": { "cssom": "~0.3.6" } }, "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/data-urls": ["data-urls@2.0.0", "", { "dependencies": { "abab": "^2.0.3", "whatwg-mimetype": "^2.3.0", "whatwg-url": "^8.0.0" } }, "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ=="],
|
||||
@ -4059,6 +4215,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=="],
|
||||
@ -4115,8 +4273,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=="],
|
||||
@ -4125,6 +4281,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=="],
|
||||
@ -4201,6 +4359,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=="],
|
||||
@ -4217,6 +4377,12 @@
|
||||
|
||||
"css-select/domutils/dom-serializer/entities": ["entities@2.2.0", "", {}, "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="],
|
||||
|
||||
"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=="],
|
||||
@ -4241,6 +4407,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=="],
|
||||
@ -4257,6 +4425,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=="],
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "config-schema",
|
||||
"version": "1.0.0",
|
||||
"version": "2.6.0",
|
||||
"description": "Gradido Config for validate config",
|
||||
"main": "./build/index.js",
|
||||
"types": "./src/index.ts",
|
||||
@ -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"
|
||||
},
|
||||
|
||||
102
config-schema/test/testSetup.bun.ts
Normal file
102
config-schema/test/testSetup.bun.ts
Normal file
@ -0,0 +1,102 @@
|
||||
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()
|
||||
}),
|
||||
isDebugEnabled: jest.fn(() => {
|
||||
return true
|
||||
})
|
||||
}
|
||||
loggers[param] = fakeLogger
|
||||
return fakeLogger
|
||||
})
|
||||
|
||||
mock.module('log4js', () => ({
|
||||
getLogger: getLoggerMocked
|
||||
}))
|
||||
|
||||
export function getLogger(name: string) {
|
||||
if (!loggers[name]) {
|
||||
return getLoggerMocked(name)
|
||||
}
|
||||
return loggers[name]
|
||||
}
|
||||
109
config-schema/test/testSetup.vitest.ts
Normal file
109
config-schema/test/testSetup.vitest.ts
Normal file
@ -0,0 +1,109 @@
|
||||
import { vi } from 'vitest'
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
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)
|
||||
messages.push(log.additional.map((d) => {
|
||||
if (typeof d === 'object' && d.toString() === '[object Object]') {
|
||||
return JSON.stringify(d)
|
||||
}
|
||||
if (d) {
|
||||
return d.toString()
|
||||
}
|
||||
}).filter((d) => d))
|
||||
process.stdout.write(`${log.logger} [${log.level}] ${log.context} ${messages.join(' ')}\n`)
|
||||
}
|
||||
}
|
||||
|
||||
export function clearLogs(): void {
|
||||
logs.length = 0
|
||||
}
|
||||
|
||||
const getLoggerMocked = vi.fn().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: vi.fn((key: string, value: string) => {
|
||||
fakeLogger.context.set(key, value)
|
||||
}),
|
||||
trace: vi.fn((message: string, ...args: any[]) => {
|
||||
addLog('trace', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
debug: vi.fn((message: string, ...args: any[]) => {
|
||||
addLog('debug', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
warn: vi.fn((message: string, ...args: any[]) => {
|
||||
addLog('warn', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
info: vi.fn((message: string, ...args: any[]) => {
|
||||
addLog('info', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
error: vi.fn((message: string, ...args: any[]) => {
|
||||
addLog('error', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
fatal: vi.fn((message: string, ...args: any[]) => {
|
||||
addLog('fatal', message, param, fakeLogger.context, args)
|
||||
}),
|
||||
removeContext: vi.fn((key: string) => {
|
||||
fakeLogger.context.delete(key)
|
||||
}),
|
||||
clearContext: vi.fn(() => {
|
||||
fakeLogger.context.clear()
|
||||
}),
|
||||
isDebugEnabled: vi.fn(() => {
|
||||
return true
|
||||
})
|
||||
}
|
||||
loggers[param] = fakeLogger
|
||||
return fakeLogger
|
||||
})
|
||||
|
||||
vi.mock('log4js', () => {
|
||||
const originalModule = vi.importActual('log4js')
|
||||
return {
|
||||
__esModule: true,
|
||||
...originalModule,
|
||||
getLogger: getLoggerMocked
|
||||
}
|
||||
})
|
||||
|
||||
export function getLogger(name: string) {
|
||||
if (!loggers[name]) {
|
||||
return getLoggerMocked(name)
|
||||
}
|
||||
return loggers[name]
|
||||
}
|
||||
10
core/README.md
Normal file
10
core/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# core
|
||||
Gradido Core Code, High-Level Shared Code, with dependencies on other modules
|
||||
|
||||
## Bun-Compatibility
|
||||
Full bun compatible
|
||||
|
||||
## Validation
|
||||
All validation logic used across more than one module
|
||||
Anything more complex than simple zod schemas is implemented here
|
||||
Tests written for bun
|
||||
2
core/bunfig.toml
Normal file
2
core/bunfig.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[test]
|
||||
preload = ["../config-schema/test/testSetup.bun.ts"]
|
||||
40
core/package.json
Normal file
40
core/package.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "core",
|
||||
"version": "2.6.0",
|
||||
"description": "Gradido Core Code, High-Level Shared Code, with dependencies on other modules",
|
||||
"main": "./build/index.js",
|
||||
"types": "./src/index.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./build/index.js",
|
||||
"require": "./build/index.js"
|
||||
}
|
||||
},
|
||||
"repository": "https://github.com/gradido/gradido/core",
|
||||
"author": "Gradido Academy - https://www.gradido.net",
|
||||
"license": "Apache-2.0",
|
||||
"private": true,
|
||||
"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"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.0.0",
|
||||
"@types/node": "^17.0.21",
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"database": "*",
|
||||
"esbuild": "^0.25.2",
|
||||
"log4js": "^6.9.1",
|
||||
"zod": "^3.25.61"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
}
|
||||
1
core/src/config/const.ts
Normal file
1
core/src/config/const.ts
Normal file
@ -0,0 +1 @@
|
||||
export const LOG4JS_BASE_CATEGORY_NAME = 'core'
|
||||
1
core/src/index.ts
Normal file
1
core/src/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './validation/user'
|
||||
68
core/src/validation/user.test.ts
Normal file
68
core/src/validation/user.test.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import { validateAlias } from './user'
|
||||
import { getLogger } from '../../../config-schema/test/testSetup.bun'
|
||||
import { describe, it, expect, beforeEach, mock, jest } from 'bun:test'
|
||||
import { aliasExists } from 'database'
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '../config/const'
|
||||
|
||||
const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.validation.user`)
|
||||
|
||||
mock.module('database', () => ({
|
||||
aliasExists: jest.fn(),
|
||||
}))
|
||||
mock.module('shared/src/schema/user.schema', () => ({
|
||||
aliasSchema: {
|
||||
parse: jest.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
describe('validate alias', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('zod throw an validation error', () => {
|
||||
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([
|
||||
// error vor zod v4
|
||||
/*expect.objectContaining({
|
||||
code: 'too_small',
|
||||
minimum: 3,
|
||||
origin: 'string',
|
||||
message: 'Given alias is too short',
|
||||
}), */
|
||||
expect.objectContaining({
|
||||
code: 'too_small',
|
||||
exact: false,
|
||||
inclusive: true,
|
||||
minimum: 3,
|
||||
type: 'string',
|
||||
message: 'Given alias is too short',
|
||||
path: [],
|
||||
}),
|
||||
]),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
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('valid alias', () => {
|
||||
it('resolves to true', async () => {
|
||||
(aliasExists as jest.Mock).mockResolvedValue(false)
|
||||
expect(validateAlias('bibi')).resolves.toEqual(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
27
core/src/validation/user.ts
Normal file
27
core/src/validation/user.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { ZodError } from 'zod'
|
||||
import { getLogger } from 'log4js'
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '../config/const'
|
||||
import { aliasExists } from 'database'
|
||||
import { aliasSchema } from 'shared'
|
||||
|
||||
const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.validation.user`)
|
||||
|
||||
export async function validateAlias(alias: string): Promise<true> {
|
||||
try {
|
||||
aliasSchema.parse(alias)
|
||||
} catch (err) {
|
||||
if (err instanceof ZodError || (err as Error).name === 'ZodError') {
|
||||
// throw only first error, but log all errors
|
||||
logger.warn('invalid alias', alias, (err as ZodError).errors)
|
||||
throw new Error((err as ZodError).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
|
||||
}
|
||||
73
core/tsconfig.json
Normal file
73
core/tsconfig.json
Normal file
@ -0,0 +1,73 @@
|
||||
{
|
||||
"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'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
||||
// "lib": [], /* Specify library files to be included in the compilation. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
|
||||
"declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
"declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./build/outfile.js", /* Concatenate and emit output to single file. */
|
||||
"outDir": "./build", /* Redirect output structure to the directory. */
|
||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
"composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
"strictPropertyInitialization": false, /* Enable strict checking of property initialization in classes. */
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": ".", /* Base directory to resolve non-absolute module names. */
|
||||
// "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": ["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. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
"experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
"emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
|
||||
/* Advanced Options */
|
||||
"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). */
|
||||
"exclude": ["**/*.test.ts", "**/*.spec.ts", "test/*", "**/bun.d.ts"],
|
||||
}
|
||||
@ -55,8 +55,8 @@ ENV PATH="/root/.bun/bin:${PATH}"
|
||||
##################################################################################
|
||||
FROM bun-base as installer
|
||||
|
||||
COPY --chown=app:app ./database .
|
||||
RUN bun install --production --no-cache --frozen-lockfile
|
||||
COPY --chown=app:app . .
|
||||
RUN bun install --filter database --production --no-cache --frozen-lockfile
|
||||
|
||||
##################################################################################
|
||||
# Build ##########################################################################
|
||||
@ -64,7 +64,8 @@ RUN bun install --production --no-cache --frozen-lockfile
|
||||
FROM installer as build
|
||||
|
||||
RUN bun install --no-cache --frozen-lockfile \
|
||||
yarn build && yarn typecheck
|
||||
&& cd shared && yarn build \
|
||||
&& cd ../database && yarn build && yarn typecheck
|
||||
|
||||
##################################################################################
|
||||
# PRODUCTION IMAGE ###############################################################
|
||||
@ -72,8 +73,7 @@ RUN bun install --no-cache --frozen-lockfile \
|
||||
FROM base as production
|
||||
|
||||
COPY --chown=app:app --from=installer ${DOCKER_WORKDIR}/src ./src
|
||||
COPY --chown=app:app --from=installer ${DOCKER_WORKDIR}/migrations ./migrations
|
||||
COPY --chown=app:app --from=installer ${DOCKER_WORKDIR}/entity ./entity
|
||||
COPY --chown=app:app --from=installer ${DOCKER_WORKDIR}/migration ./migration
|
||||
COPY --chown=app:app --from=installer ${DOCKER_WORKDIR}/node_modules ./node_modules
|
||||
COPY --chown=app:app --from=installer ${DOCKER_WORKDIR}/package.json ./package.json
|
||||
COPY --chown=app:app --from=installer ${DOCKER_WORKDIR}/tsconfig.json ./tsconfig.json
|
||||
@ -83,7 +83,6 @@ COPY --chown=app:app --from=installer ${DOCKER_WORKDIR}/tsconfig.json ./tsconfig
|
||||
##################################################################################
|
||||
FROM production as up
|
||||
|
||||
|
||||
# Run command
|
||||
CMD /bin/sh -c "yarn up"
|
||||
|
||||
|
||||
@ -49,3 +49,5 @@ yarn clear
|
||||
```
|
||||
|
||||
|
||||
## Tests
|
||||
Currently written for vitest, but can be transformed into bun test after switching out TypeORM with DrizzleORM
|
||||
@ -13,26 +13,39 @@
|
||||
"repository": "https://github.com/gradido/gradido/database",
|
||||
"author": "Gradido Academy - https://www.gradido.net",
|
||||
"license": "Apache-2.0",
|
||||
"private": false,
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "tsx ./esbuild.config.ts",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"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 --reporter verbose --no-file-parallelism 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",
|
||||
"crypto-random-bigint": "^2.1.1",
|
||||
"jest": "27.2.4",
|
||||
"ts-jest": "27.0.5",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^4.9.5",
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/uuid": "^8.3.4",
|
||||
@ -45,10 +58,11 @@
|
||||
"log4js": "^6.9.1",
|
||||
"mysql2": "^2.3.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"shared": "*",
|
||||
"source-map-support": "^0.5.21",
|
||||
"ts-mysql-migrate": "^1.0.2",
|
||||
"tsx": "^4.19.4",
|
||||
"typeorm": "^0.3.22",
|
||||
"tsx": "^4.20.3",
|
||||
"typeorm": "^0.3.25",
|
||||
"uuid": "^8.3.2",
|
||||
"wkx": "^0.5.0"
|
||||
},
|
||||
|
||||
@ -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 as DbCommunity } 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 DbCommunity.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 },
|
||||
})
|
||||
}
|
||||
6
database/src/queries/index.ts
Normal file
6
database/src/queries/index.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '../config/const'
|
||||
|
||||
export * from './user'
|
||||
export * from './communities'
|
||||
|
||||
export const LOG4JS_QUERIES_CATEGORY_NAME = `${LOG4JS_BASE_CATEGORY_NAME}.queries`
|
||||
141
database/src/queries/user.test.ts
Normal file
141
database/src/queries/user.test.ts
Normal file
@ -0,0 +1,141 @@
|
||||
import { User as DbUser, UserContact as DbUserContact, Community as DbCommunity } from '..'
|
||||
import { AppDatabase } from '../AppDatabase'
|
||||
import { aliasExists, findUserByIdentifier } from './user'
|
||||
import { userFactory } from '../seeds/factory/user'
|
||||
import { bibiBloxberg } from '../seeds/users/bibi-bloxberg'
|
||||
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
|
||||
import { createCommunity } from '../seeds/homeCommunity'
|
||||
import { peterLustig } from '../seeds/users/peter-lustig'
|
||||
import { bobBaumeister } from '../seeds/users/bob-baumeister'
|
||||
import { getLogger, printLogs, clearLogs } from '../../../config-schema/test/testSetup.vitest'
|
||||
import { LOG4JS_QUERIES_CATEGORY_NAME } from '.'
|
||||
import { beforeEach } from 'node:test'
|
||||
|
||||
const db = AppDatabase.getInstance()
|
||||
const userIdentifierLoggerName = `${LOG4JS_QUERIES_CATEGORY_NAME}.user.findUserByIdentifier`
|
||||
|
||||
beforeAll(async () => {
|
||||
await db.init()
|
||||
})
|
||||
afterAll(async () => {
|
||||
await db.destroy()
|
||||
})
|
||||
|
||||
describe('user.queries', () => {
|
||||
describe('aliasExists', () => {
|
||||
beforeAll(async () => {
|
||||
await DbUser.clear()
|
||||
await DbUserContact.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)
|
||||
})
|
||||
})
|
||||
|
||||
describe('findUserByIdentifier', () => {
|
||||
let homeCom: DbCommunity
|
||||
let communityUuid: string
|
||||
let communityName: string
|
||||
let userBibi: DbUser
|
||||
|
||||
beforeAll(async () => {
|
||||
await DbUser.clear()
|
||||
await DbUserContact.clear()
|
||||
await DbCommunity.clear()
|
||||
|
||||
homeCom = await createCommunity(false)
|
||||
communityUuid = homeCom.communityUuid!
|
||||
communityName = homeCom.name!
|
||||
userBibi = await userFactory(bibiBloxberg)
|
||||
await userFactory(peterLustig)
|
||||
await userFactory(bobBaumeister)
|
||||
})
|
||||
beforeEach(() => {
|
||||
clearLogs()
|
||||
})
|
||||
describe('communityIdentifier is community uuid', () => {
|
||||
it('userIdentifier is gradido id', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.gradidoID, communityUuid)
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
|
||||
it('userIdentifier is alias', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.alias, communityUuid)
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
|
||||
it('userIdentifier is email', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.emailContact.email, communityUuid)
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
it('userIdentifier is unknown', async () => {
|
||||
const user = await findUserByIdentifier('unknown', communityUuid)
|
||||
expect(user).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('communityIdentifier is community name', () => {
|
||||
it('userIdentifier is gradido id', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.gradidoID, communityName)
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
|
||||
it('userIdentifier is alias', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.alias, communityName)
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
|
||||
it('userIdentifier is email', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.emailContact.email, communityName)
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
})
|
||||
describe('communityIdentifier is unknown', () => {
|
||||
it('userIdentifier is gradido id', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.gradidoID, 'unknown')
|
||||
expect(user).toBeNull()
|
||||
})
|
||||
it('userIdentifier is unknown', async () => {
|
||||
const user = await findUserByIdentifier('unknown', communityUuid)
|
||||
expect(user).toBeNull()
|
||||
})
|
||||
})
|
||||
describe('communityIdentifier is empty', () => {
|
||||
it('userIdentifier is gradido id', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.gradidoID)
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
|
||||
it('userIdentifier is alias', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.alias)
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
|
||||
it('userIdentifier is email', async () => {
|
||||
const user = await findUserByIdentifier(userBibi.emailContact.email)
|
||||
expect(user).toMatchObject(userBibi)
|
||||
})
|
||||
it('userIdentifier is unknown type', async () => {
|
||||
const user = await findUserByIdentifier('sa')
|
||||
printLogs()
|
||||
expect(getLogger(userIdentifierLoggerName).warn).toHaveBeenCalledWith('Unknown identifier type', 'sa')
|
||||
expect(user).toBeNull()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
62
database/src/queries/user.ts
Normal file
62
database/src/queries/user.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { Raw } from 'typeorm'
|
||||
import { Community, User as DbUser, UserContact as DbUserContact } from '../entity'
|
||||
import { FindOptionsWhere } from 'typeorm'
|
||||
import { aliasSchema, emailSchema, uuidv4Schema, urlSchema } from 'shared'
|
||||
import { getLogger } from 'log4js'
|
||||
import { LOG4JS_QUERIES_CATEGORY_NAME } from './index'
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param identifier could be gradidoID, alias or email of user
|
||||
* @param communityIdentifier could be uuid or name of community
|
||||
* @returns
|
||||
*/
|
||||
export const findUserByIdentifier = async (
|
||||
identifier: string,
|
||||
communityIdentifier?: string,
|
||||
): Promise<DbUser | null> => {
|
||||
const communityWhere: FindOptionsWhere<Community> = urlSchema.safeParse(communityIdentifier).success
|
||||
? { url: communityIdentifier }
|
||||
: uuidv4Schema.safeParse(communityIdentifier).success
|
||||
? { communityUuid: communityIdentifier }
|
||||
: { name: communityIdentifier }
|
||||
|
||||
if (uuidv4Schema.safeParse(identifier).success) {
|
||||
return DbUser.findOne({
|
||||
where: { gradidoID: identifier, community: communityWhere },
|
||||
relations: ['emailContact', 'community'],
|
||||
})
|
||||
} else if (emailSchema.safeParse(identifier).success) {
|
||||
const userContact = await DbUserContact.findOne({
|
||||
where: {
|
||||
email: identifier,
|
||||
emailChecked: true,
|
||||
user: {
|
||||
community: communityWhere,
|
||||
},
|
||||
},
|
||||
relations: { user: { community: true } },
|
||||
})
|
||||
if (userContact) {
|
||||
// TODO: remove circular reference
|
||||
const user = userContact.user
|
||||
user.emailContact = userContact
|
||||
return user
|
||||
}
|
||||
} else if (aliasSchema.safeParse(identifier).success) {
|
||||
return await DbUser.findOne({
|
||||
where: { alias: identifier, community: communityWhere },
|
||||
relations: ['emailContact', 'community'],
|
||||
})
|
||||
}
|
||||
// should don't happen often, so we create only in the rare case a logger for it
|
||||
getLogger(`${LOG4JS_QUERIES_CATEGORY_NAME}.user.findUserByIdentifier`).warn('Unknown identifier type', identifier)
|
||||
return null
|
||||
}
|
||||
43
database/src/seeds/factory/user.ts
Normal file
43
database/src/seeds/factory/user.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { UserInterface } from '../users/UserInterface'
|
||||
import { User, UserContact } from '../../entity'
|
||||
import { v4 } from 'uuid'
|
||||
import { UserContactType, OptInType, PasswordEncryptionType } from 'shared'
|
||||
import { getHomeCommunity } from '../../queries/communities'
|
||||
import random from 'crypto-random-bigint'
|
||||
|
||||
export const userFactory = async (user: UserInterface): Promise<User> => {
|
||||
let dbUserContact = new UserContact()
|
||||
|
||||
dbUserContact.email = user.email ?? ''
|
||||
dbUserContact.type = 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 = random(64).toString()
|
||||
dbUserContact.emailOptInTypeId = OptInType.EMAIL_OPT_IN_REGISTER
|
||||
dbUserContact.emailChecked = true
|
||||
dbUser.password = random(64)
|
||||
dbUser.passwordEncryptionType = PasswordEncryptionType.GRADIDO_ID
|
||||
}
|
||||
const homeCommunity = await getHomeCommunity()
|
||||
if (homeCommunity) {
|
||||
dbUser.community = homeCommunity
|
||||
dbUser.communityUuid = homeCommunity.communityUuid!
|
||||
}
|
||||
// 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',
|
||||
}
|
||||
@ -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,9 @@
|
||||
"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
|
||||
},
|
||||
"exclude": ["**/*.test.ts", "**/*.spec.ts", "test/*"]
|
||||
}
|
||||
|
||||
@ -13,10 +13,16 @@
|
||||
"up:dht_test": {
|
||||
"cache": false
|
||||
},
|
||||
"up:test": {
|
||||
"cache": false
|
||||
},
|
||||
"up": {
|
||||
"cache": false,
|
||||
"dependsOn": ["build"]
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": ["up:test", "^build"]
|
||||
},
|
||||
"down": {
|
||||
"cache": false,
|
||||
"dependsOn": ["build"]
|
||||
|
||||
7
database/vitest.config.js
Normal file
7
database/vitest.config.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
setupFiles: '../config-schema/test/testSetup.vitest.ts',
|
||||
},
|
||||
})
|
||||
1060
database/yarn.lock
1060
database/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@ module.exports = {
|
||||
verbose: false,
|
||||
preset: 'ts-jest',
|
||||
collectCoverage: false,
|
||||
collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**', '!src/seeds/**', '!build/**'],
|
||||
collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**', '!build/**'],
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
lines: 82,
|
||||
|
||||
@ -47,8 +47,9 @@
|
||||
"prettier": "^2.8.8",
|
||||
"source-map-support": "^0.5.21",
|
||||
"ts-jest": "27.1.4",
|
||||
"tsconfig-paths": "^4.1.1",
|
||||
"tsx": "^4.19.4",
|
||||
"typeorm": "^0.3.22",
|
||||
"typeorm": "^0.3.25",
|
||||
"typescript": "^4.9.5",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
|
||||
@ -3,6 +3,7 @@ import {
|
||||
CommunityLoggingView,
|
||||
Community as DbCommunity,
|
||||
FederatedCommunity as DbFederatedCommunity,
|
||||
getHomeCommunity,
|
||||
} from 'database'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
@ -233,7 +234,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
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { contributionDateFormatter } from '@test/helpers'
|
||||
import { contributionDateFormatter } from './helpers'
|
||||
|
||||
describe('contributionDateFormatter', () => {
|
||||
it('formats the date correctly', () => {
|
||||
|
||||
@ -16,7 +16,9 @@ const context = {
|
||||
export const cleanDB = async () => {
|
||||
// this only works as long we do not have foreign key constraints
|
||||
for (const entity of entities) {
|
||||
await resetEntity(entity)
|
||||
if (entity.name !== 'Migration') {
|
||||
await resetEntity(entity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,10 +2,10 @@
|
||||
"extends": ["//"],
|
||||
"tasks": {
|
||||
"test": {
|
||||
"dependsOn": ["config-schema#build", "database#build", "database#up:dht_test"]
|
||||
"dependsOn": ["database#up:dht_test", "^build"]
|
||||
},
|
||||
"dev": {
|
||||
"dependsOn": ["config-schema#build", "database#build", "database#up"]
|
||||
"dependsOn": ["database#up", "^build"]
|
||||
},
|
||||
"start": {
|
||||
"dependsOn": ["database#up", "build"]
|
||||
|
||||
@ -63,7 +63,7 @@
|
||||
"ts-jest": "27.0.5",
|
||||
"tsconfig-paths": "^4.1.1",
|
||||
"type-graphql": "^1.1.1",
|
||||
"typeorm": "^0.3.22",
|
||||
"typeorm": "^0.3.25",
|
||||
"typescript": "^4.9.5",
|
||||
"uuid": "8.3.2"
|
||||
},
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {
|
||||
DECAY_START_TIME,
|
||||
GRAPHIQL,
|
||||
LOG4JS_CONFIG_PLACEHOLDER,
|
||||
LOG_FILES_BASE_PATH,
|
||||
@ -10,7 +9,6 @@ import {
|
||||
import Joi from 'joi'
|
||||
|
||||
export const schema = Joi.object({
|
||||
DECAY_START_TIME,
|
||||
GRAPHIQL,
|
||||
LOG4JS_CONFIG_PLACEHOLDER,
|
||||
LOG_FILES_BASE_PATH,
|
||||
|
||||
@ -1,14 +1,6 @@
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
|
||||
interface DecayInterface {
|
||||
balance: Decimal
|
||||
decay: Decimal
|
||||
roundedDecay: Decimal
|
||||
start: Date | null
|
||||
end: Date | null
|
||||
duration: number | null
|
||||
}
|
||||
import { Decay as DecayInterface} from 'shared'
|
||||
|
||||
@ObjectType()
|
||||
export class Decay {
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { findUserByIdentifier } from '@/graphql/util/findUserByIdentifier'
|
||||
import { fullName } from '@/graphql/util/fullName'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import {
|
||||
Community as DbCommunity,
|
||||
PendingTransaction as DbPendingTransaction,
|
||||
PendingTransactionLoggingView,
|
||||
findUserByIdentifier
|
||||
} from 'database'
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { getLogger } from 'log4js'
|
||||
@ -43,14 +43,14 @@ export class SendCoinsResolver {
|
||||
)
|
||||
}
|
||||
let receiverUser
|
||||
try {
|
||||
// second check if receiver user exists in this community
|
||||
receiverUser = await findUserByIdentifier(
|
||||
args.recipientUserIdentifier,
|
||||
args.recipientCommunityUuid,
|
||||
)
|
||||
} catch (err) {
|
||||
logger.error('Error in findUserByIdentifier:', err)
|
||||
|
||||
// second check if receiver user exists in this community
|
||||
receiverUser = await findUserByIdentifier(
|
||||
args.recipientUserIdentifier,
|
||||
args.recipientCommunityUuid,
|
||||
)
|
||||
if (!receiverUser) {
|
||||
logger.error('Error in findUserByIdentifier:')
|
||||
throw new LogError(
|
||||
`voteForSendCoins with unknown recipientUserIdentifier in the community=`,
|
||||
homeCom.name,
|
||||
@ -126,11 +126,11 @@ export class SendCoinsResolver {
|
||||
)
|
||||
}
|
||||
let receiverUser
|
||||
try {
|
||||
// second check if receiver user exists in this community
|
||||
receiverUser = await findUserByIdentifier(args.recipientUserIdentifier)
|
||||
} catch (err) {
|
||||
logger.error('Error in findUserByIdentifier:', err)
|
||||
|
||||
// second check if receiver user exists in this community
|
||||
receiverUser = await findUserByIdentifier(args.recipientUserIdentifier)
|
||||
if (!receiverUser) {
|
||||
logger.error('Error in findUserByIdentifier')
|
||||
throw new LogError(
|
||||
`revertSendCoins with unknown recipientUserIdentifier in the community=`,
|
||||
homeCom.name,
|
||||
@ -193,12 +193,11 @@ export class SendCoinsResolver {
|
||||
args.recipientCommunityUuid,
|
||||
)
|
||||
}
|
||||
let receiverUser
|
||||
try {
|
||||
// second check if receiver user exists in this community
|
||||
receiverUser = await findUserByIdentifier(args.recipientUserIdentifier)
|
||||
} catch (err) {
|
||||
logger.error('Error in findUserByIdentifier:', err)
|
||||
|
||||
// second check if receiver user exists in this community
|
||||
const receiverUser = await findUserByIdentifier(args.recipientUserIdentifier)
|
||||
if (!receiverUser) {
|
||||
logger.error('Error in findUserByIdentifier')
|
||||
throw new LogError(
|
||||
`settleSendCoins with unknown recipientUserIdentifier in the community=`,
|
||||
homeCom.name,
|
||||
@ -265,13 +264,12 @@ export class SendCoinsResolver {
|
||||
`revertSettledSendCoins with wrong recipientCommunityUuid`,
|
||||
args.recipientCommunityUuid,
|
||||
)
|
||||
}
|
||||
let receiverUser
|
||||
try {
|
||||
// second check if receiver user exists in this community
|
||||
receiverUser = await findUserByIdentifier(args.recipientUserIdentifier)
|
||||
} catch (err) {
|
||||
logger.error('Error in findUserByIdentifier:', err)
|
||||
}
|
||||
|
||||
// second check if receiver user exists in this community
|
||||
const receiverUser = await findUserByIdentifier(args.recipientUserIdentifier)
|
||||
if (!receiverUser) {
|
||||
logger.error('Error in findUserByIdentifier')
|
||||
throw new LogError(
|
||||
`revertSettledSendCoins with unknown recipientUserIdentifier in the community=`,
|
||||
homeCom.name,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { calculateDecay } from '@/graphql/util/decay'
|
||||
import { calculateDecay } from 'shared'
|
||||
import { getLastTransaction } from '@/graphql/util/getLastTransaction'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import { Decay } from '../model/Decay'
|
||||
@ -13,7 +13,7 @@ export async function calculateRecipientBalance(
|
||||
return null
|
||||
}
|
||||
|
||||
const decay = calculateDecay(lastTransaction.balance, lastTransaction.balanceDate, time)
|
||||
const decay = new Decay(calculateDecay(lastTransaction.balance, lastTransaction.balanceDate, time))
|
||||
|
||||
const balance = decay.balance.add(amount.toString())
|
||||
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
import { User as DbUser, UserContact as DbUserContact } from 'database'
|
||||
import { validate, version } from 'uuid'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
import { VALID_ALIAS_REGEX } from './validateAlias'
|
||||
|
||||
export const findUserByIdentifier = async (
|
||||
identifier: string,
|
||||
communityIdentifier?: string,
|
||||
): Promise<DbUser> => {
|
||||
let user: DbUser | null
|
||||
if (validate(identifier) && version(identifier) === 4) {
|
||||
user = await DbUser.findOne({
|
||||
where: { gradidoID: identifier, communityUuid: communityIdentifier },
|
||||
relations: ['emailContact'],
|
||||
})
|
||||
if (!user) {
|
||||
throw new LogError('No user found to given identifier(s)', identifier, communityIdentifier)
|
||||
}
|
||||
} else if (/^.{2,}@.{2,}\..{2,}$/.exec(identifier)) {
|
||||
const userContact = await DbUserContact.findOne({
|
||||
where: {
|
||||
email: identifier,
|
||||
emailChecked: true,
|
||||
},
|
||||
relations: ['user'],
|
||||
})
|
||||
if (!userContact) {
|
||||
throw new LogError('No user with this credentials', identifier)
|
||||
}
|
||||
if (!userContact.user) {
|
||||
throw new LogError('No user to given contact', identifier)
|
||||
}
|
||||
if (userContact.user.communityUuid !== communityIdentifier) {
|
||||
throw new LogError(
|
||||
'Found user to given contact, but belongs to other community',
|
||||
identifier,
|
||||
communityIdentifier,
|
||||
)
|
||||
}
|
||||
user = userContact.user
|
||||
user.emailContact = userContact
|
||||
} else if (VALID_ALIAS_REGEX.exec(identifier)) {
|
||||
user = await DbUser.findOne({
|
||||
where: { alias: identifier, communityUuid: communityIdentifier },
|
||||
relations: ['emailContact'],
|
||||
})
|
||||
if (!user) {
|
||||
throw new LogError('No user found to given identifier(s)', identifier, communityIdentifier)
|
||||
}
|
||||
} else {
|
||||
throw new LogError('Unknown identifier type', identifier)
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
import { User as DbUser } from 'database'
|
||||
import { Raw } from 'typeorm'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
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 validateAlias = async (alias: string): Promise<boolean> => {
|
||||
if (alias.length < 3) {
|
||||
throw new LogError('Given alias is too short', alias)
|
||||
}
|
||||
if (alias.length > 20) {
|
||||
throw new LogError('Given alias is too long', alias)
|
||||
}
|
||||
if (!alias.match(VALID_ALIAS_REGEX)) {
|
||||
throw new LogError('Invalid characters in alias', alias)
|
||||
}
|
||||
if (RESERVED_ALIAS.includes(alias.toLowerCase())) {
|
||||
throw new LogError('Alias is not allowed', alias)
|
||||
}
|
||||
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
|
||||
}
|
||||
@ -21,7 +21,9 @@ const context = {
|
||||
export const cleanDB = async () => {
|
||||
// this only works as long we do not have foreign key constraints
|
||||
for (const entity of entities) {
|
||||
await resetEntity(entity)
|
||||
if (entity.name !== 'Migration') {
|
||||
await resetEntity(entity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@
|
||||
// "@arg/*": ["src/graphql/arg/*"],
|
||||
// "@enum/*": ["src/graphql/enum/*"],
|
||||
// "@model/*": ["src/graphql/model/*"],
|
||||
"@repository/*": ["src/typeorm/repository/*"],
|
||||
// "@repository/*": ["src/typeorm/repository/*"],
|
||||
"@test/*": ["test/*"],
|
||||
/* common */
|
||||
// "@common/*": ["../common/src/*"],
|
||||
|
||||
@ -2,10 +2,10 @@
|
||||
"extends": ["//"],
|
||||
"tasks": {
|
||||
"test": {
|
||||
"dependsOn": ["database#up:federation_test", "config-schema#build", "database#build"]
|
||||
"dependsOn": ["database#up:federation_test", "^build"]
|
||||
},
|
||||
"dev": {
|
||||
"dependsOn": ["database#up"]
|
||||
"dependsOn": ["database#up", "^build"]
|
||||
},
|
||||
"start": {
|
||||
"dependsOn": ["database#up", "build"]
|
||||
|
||||
@ -81,7 +81,7 @@
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"chokidar-cli": "^3.0.0",
|
||||
"concurrently": "^9.1.2",
|
||||
"config-schema": "*",
|
||||
"config-schema": "2.6.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"dotenv-webpack": "^7.0.3",
|
||||
"eslint": "8.57.1",
|
||||
|
||||
@ -12,10 +12,12 @@
|
||||
"admin",
|
||||
"backend",
|
||||
"config-schema",
|
||||
"core",
|
||||
"database",
|
||||
"dht-node",
|
||||
"federation",
|
||||
"frontend"
|
||||
"frontend",
|
||||
"shared"
|
||||
],
|
||||
"scripts": {
|
||||
"release": "scripts/release.sh",
|
||||
|
||||
@ -6,6 +6,9 @@ PROJECT_DIR="${SCRIPT_DIR}/../"
|
||||
FRONTEND_DIR="${PROJECT_DIR}/frontend/"
|
||||
BACKEND_DIR="${PROJECT_DIR}/backend/"
|
||||
DATABASE_DIR="${PROJECT_DIR}/database/"
|
||||
SHARED_DIR="${PROJECT_DIR}/shared/"
|
||||
CONFIG_SCHEMA_DIR="${PROJECT_DIR}/config-schema/"
|
||||
CORE_DIR="${PROJECT_DIR}/core/"
|
||||
ADMIN_DIR="${PROJECT_DIR}/admin/"
|
||||
DHTNODE_DIR="${PROJECT_DIR}/dht-node/"
|
||||
FEDERATION_DIR="${PROJECT_DIR}/federation/"
|
||||
@ -27,6 +30,12 @@ cd ${BACKEND_DIR}
|
||||
yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version ${VERSION}
|
||||
cd ${DATABASE_DIR}
|
||||
yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version ${VERSION}
|
||||
cd ${SHARED_DIR}
|
||||
yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version ${VERSION}
|
||||
cd ${CONFIG_SCHEMA_DIR}
|
||||
yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version ${VERSION}
|
||||
cd ${CORE_DIR}
|
||||
yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version ${VERSION}
|
||||
cd ${ADMIN_DIR}
|
||||
yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version ${VERSION}
|
||||
cd ${DHTNODE_DIR}
|
||||
|
||||
13
shared/README.md
Normal file
13
shared/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# shared
|
||||
Gradido Shared Code, Low-Level Shared Code, without dependencies on other modules
|
||||
|
||||
## Bun-Compatibility
|
||||
Full bun compatible
|
||||
|
||||
## Enums
|
||||
All enums used across more than one module
|
||||
Additional with zod Schema but working only with zod v4 and this needs typescript 5
|
||||
|
||||
## Schemas
|
||||
All schemas for data validation used across more than one module
|
||||
Tests written for bun
|
||||
42
shared/package.json
Normal file
42
shared/package.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "shared",
|
||||
"version": "2.6.0",
|
||||
"description": "Gradido Shared Code, Low-Level Shared Code, without dependencies on other modules",
|
||||
"main": "./build/index.js",
|
||||
"types": "./src/index.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./build/index.js",
|
||||
"require": "./build/index.js"
|
||||
}
|
||||
},
|
||||
"repository": "https://github.com/gradido/gradido/shared",
|
||||
"author": "Gradido Academy - https://www.gradido.net",
|
||||
"license": "Apache-2.0",
|
||||
"private": true,
|
||||
"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"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.0.0",
|
||||
"@types/node": "^17.0.21",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"typescript": "^4.9.5",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"decimal.js-light": "^2.5.1",
|
||||
"esbuild": "^0.25.2",
|
||||
"log4js": "^6.9.1",
|
||||
"zod": "^3.25.61"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
}
|
||||
2
shared/src/const/index.ts
Normal file
2
shared/src/const/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const DECAY_START_TIME = new Date('2021-05-13T17:46:31Z')
|
||||
export const LOG4JS_BASE_CATEGORY_NAME = 'shared'
|
||||
8
shared/src/enum/OptInType.ts
Normal file
8
shared/src/enum/OptInType.ts
Normal file
@ -0,0 +1,8 @@
|
||||
// not compatible with typescript 4
|
||||
// import { enum as zEnum } from 'zod/v4-mini'
|
||||
export enum OptInType {
|
||||
EMAIL_OPT_IN_REGISTER = 1,
|
||||
EMAIL_OPT_IN_RESET_PASSWORD = 2,
|
||||
}
|
||||
|
||||
// export const OptInTypeSchema = zEnum(OptInType)
|
||||
11
shared/src/enum/PasswordEncryptionType.ts
Normal file
11
shared/src/enum/PasswordEncryptionType.ts
Normal file
@ -0,0 +1,11 @@
|
||||
// not compatible with typescript 4
|
||||
// import { enum as zEnum } from 'zod/v4-mini'
|
||||
|
||||
export enum PasswordEncryptionType {
|
||||
NO_PASSWORD = 0,
|
||||
EMAIL = 1,
|
||||
GRADIDO_ID = 2,
|
||||
}
|
||||
|
||||
// export const PasswordEncryptionTypeSchema = zEnum(PasswordEncryptionType)
|
||||
|
||||
13
shared/src/enum/RoleNames.ts
Normal file
13
shared/src/enum/RoleNames.ts
Normal file
@ -0,0 +1,13 @@
|
||||
// not compatible with typescript 4
|
||||
// import { enum as zEnum } from 'zod/v4-mini'
|
||||
|
||||
export enum RoleNames {
|
||||
UNAUTHORIZED = 'UNAUTHORIZED',
|
||||
USER = 'USER',
|
||||
MODERATOR = 'MODERATOR',
|
||||
MODERATOR_AI = 'MODERATOR_AI',
|
||||
ADMIN = 'ADMIN',
|
||||
DLT_CONNECTOR = 'DLT_CONNECTOR_ROLE',
|
||||
}
|
||||
|
||||
// export const RoleNamesSchema = zEnum(RoleNames)
|
||||
9
shared/src/enum/UserContactType.ts
Normal file
9
shared/src/enum/UserContactType.ts
Normal file
@ -0,0 +1,9 @@
|
||||
// not compatible with typescript 4
|
||||
// import { enum as zEnum } from 'zod/v4-mini'
|
||||
|
||||
export enum UserContactType {
|
||||
USER_CONTACT_EMAIL = 'EMAIL',
|
||||
USER_CONTACT_PHONE = 'PHONE',
|
||||
}
|
||||
|
||||
// export const UserContactTypeSchema = zEnum(UserContactType)
|
||||
4
shared/src/enum/index.ts
Normal file
4
shared/src/enum/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export * from './RoleNames'
|
||||
export * from './UserContactType'
|
||||
export * from './PasswordEncryptionType'
|
||||
export * from './OptInType'
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user