From 3385f88c78097e6e4c65a2a0d0fa7f79d6e2c4b4 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sat, 21 Jun 2025 14:30:02 +0200 Subject: [PATCH] add additional module core, move some code into it --- .github/workflows/test_database.yml | 4 +- .github/workflows/test_shared.yml | 2 +- backend/package.json | 8 +- .../federation/validateCommunities.test.ts | 10 +- backend/src/graphql/resolver/UserResolver.ts | 2 +- .../resolver/util/findUserByIdentifier.ts | 4 +- .../resolver/util/validateAlias.test.ts | 129 ---------------- .../graphql/resolver/util/validateAlias.ts | 46 ------ backend/test/helpers.ts | 4 +- bun.lock | 146 +++++++++--------- config-schema/package.json | 4 +- {shared => core}/bunfig.toml | 0 core/package.json | 40 +++++ {shared => core}/src/config/const.ts | 0 core/src/index.ts | 1 + core/src/schema/index.ts | 4 + core/src/schema/user.schema.test.ts | 68 ++++++++ core/src/schema/user.schema.ts | 27 ++++ core/tsconfig.json | 73 +++++++++ core/turbo.json | 24 +++ database/package.json | 5 +- database/src/AppDatabase.ts | 2 +- database/src/seeds/factory/user.ts | 8 +- dht-node/package.json | 3 +- dht-node/test/helpers.ts | 4 +- dht-node/tsconfig.json | 2 +- federation/package.json | 2 +- federation/test/helpers.ts | 4 +- frontend/package.json | 2 +- package.json | 1 + scripts/release.sh | 9 ++ shared/package.json | 7 +- shared/src/enum/OptInType.ts | 8 + shared/src/enum/PasswordEncryptionType.ts | 11 ++ shared/src/enum/RoleNames.ts | 13 ++ shared/src/enum/UserContactType.ts | 9 ++ shared/src/enum/index.ts | 4 + shared/src/index.ts | 5 +- shared/src/schema/index.ts | 5 +- shared/src/schema/user.schema.test.ts | 142 ++++------------- shared/src/schema/user.schema.ts | 29 +--- yarn.lock | 54 +++++-- 42 files changed, 479 insertions(+), 446 deletions(-) delete mode 100644 backend/src/graphql/resolver/util/validateAlias.test.ts delete mode 100644 backend/src/graphql/resolver/util/validateAlias.ts rename {shared => core}/bunfig.toml (100%) create mode 100644 core/package.json rename {shared => core}/src/config/const.ts (100%) create mode 100644 core/src/index.ts create mode 100644 core/src/schema/index.ts create mode 100644 core/src/schema/user.schema.test.ts create mode 100644 core/src/schema/user.schema.ts create mode 100644 core/tsconfig.json create mode 100644 core/turbo.json create mode 100644 shared/src/enum/OptInType.ts create mode 100644 shared/src/enum/PasswordEncryptionType.ts create mode 100644 shared/src/enum/RoleNames.ts create mode 100644 shared/src/enum/UserContactType.ts create mode 100644 shared/src/enum/index.ts diff --git a/.github/workflows/test_database.yml b/.github/workflows/test_database.yml index a4e6de787..97b0e5fe8 100644 --- a/.github/workflows/test_database.yml +++ b/.github/workflows/test_database.yml @@ -59,10 +59,10 @@ jobs: bun install --global --no-save turbo@^2 - name: Database | up + test - run: turbo test + run: turbo database#test - name: Database | reset - run: turbo reset + run: turbo database#reset lint: if: needs.files-changed.outputs.database == 'true' diff --git a/.github/workflows/test_shared.yml b/.github/workflows/test_shared.yml index 5fa1068da..8a1484655 100644 --- a/.github/workflows/test_shared.yml +++ b/.github/workflows/test_shared.yml @@ -34,7 +34,7 @@ jobs: uses: oven-sh/setup-bun@v2 - name: install dependencies - run: bun install --filter shared database --frozen-lockfile + run: bun install --filter shared --frozen-lockfile - name: typecheck run: cd shared && yarn typecheck diff --git a/backend/package.json b/backend/package.json index aeb6fcb5e..cd06351aa 100644 --- a/backend/package.json +++ b/backend/package.json @@ -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", diff --git a/backend/src/federation/validateCommunities.test.ts b/backend/src/federation/validateCommunities.test.ts index 160068140..ecb78124a 100644 --- a/backend/src/federation/validateCommunities.test.ts +++ b/backend/src/federation/validateCommunities.test.ts @@ -2,12 +2,12 @@ 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 { LOG4JS_FEDERATION_CATEGORY_NAME } from '@/federation' import { LOG4JS_FEDERATION_CLIENT1_0_CATEGORY_NAME } from '@/federation/client/1_0' import { cleanDB, testEnvironment } from '@test/helpers' -import { clearLogs, getLogger, printLogs } from 'config-schema/test/testSetup' +import { getLogger } from 'config-schema/test/testSetup' import { validateCommunities } from './validateCommunities' @@ -204,7 +204,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() }) @@ -271,7 +271,7 @@ describe('validate Communities', () => { }) .execute() - await DbFederatedCommunity.update({}, { verifiedAt: null }) + await DbFederatedCommunity.update({ id: Not(0) }, { verifiedAt: null }) // jest.clearAllMocks() await validateCommunities() }) @@ -323,7 +323,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() }) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 197ff3e6c..f7688d1ca 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -103,7 +103,7 @@ 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' diff --git a/backend/src/graphql/resolver/util/findUserByIdentifier.ts b/backend/src/graphql/resolver/util/findUserByIdentifier.ts index 1bdb186ce..ef8b91c2c 100644 --- a/backend/src/graphql/resolver/util/findUserByIdentifier.ts +++ b/backend/src/graphql/resolver/util/findUserByIdentifier.ts @@ -6,7 +6,7 @@ import { validate, version } from 'uuid' import { LogError } from '@/server/LogError' import { isEMail, isUUID4 } from '@/util/validate' -import { VALID_ALIAS_REGEX } from './validateAlias' +import { aliasSchema } from 'shared' /** * @@ -49,7 +49,7 @@ export const findUserByIdentifier = async ( } user = userContact.user user.emailContact = userContact - } else if (VALID_ALIAS_REGEX.exec(identifier)) { + } else if (aliasSchema.safeParse(identifier).success) { user = await DbUser.findOne({ where: { alias: identifier, community: communityWhere }, relations: ['emailContact', 'community'], diff --git a/backend/src/graphql/resolver/util/validateAlias.test.ts b/backend/src/graphql/resolver/util/validateAlias.test.ts deleted file mode 100644 index f10f54886..000000000 --- a/backend/src/graphql/resolver/util/validateAlias.test.ts +++ /dev/null @@ -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) - }) - }) - }) -}) diff --git a/backend/src/graphql/resolver/util/validateAlias.ts b/backend/src/graphql/resolver/util/validateAlias.ts deleted file mode 100644 index 4eccad63f..000000000 --- a/backend/src/graphql/resolver/util/validateAlias.ts +++ /dev/null @@ -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 => { - 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 -} diff --git a/backend/test/helpers.ts b/backend/test/helpers.ts index a966eccf6..c7f533931 100644 --- a/backend/test/helpers.ts +++ b/backend/test/helpers.ts @@ -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) + } } } diff --git a/bun.lock b/bun.lock index 6e2eb4afe..dbf19bd65 100644 --- a/bun.lock +++ b/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", @@ -172,7 +174,22 @@ "@biomejs/biome": "2.0.0", "@types/node": "^17.0.21", "jest": "27.2.4", - "typescript": "^5.8.3", + "typescript": "^4.9.5", + }, + }, + "core": { + "name": "core", + "version": "1.0.0", + "dependencies": { + "database": "workspace:*", + "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": { @@ -189,10 +206,11 @@ "log4js": "^6.9.1", "mysql2": "^2.3.0", "reflect-metadata": "^0.1.13", + "shared": "workspace:*", "source-map-support": "^0.5.21", "ts-mysql-migrate": "^1.0.2", "tsx": "^4.20.3", - "typeorm": "^0.3.22", + "typeorm": "^0.3.25", "uuid": "^8.3.2", "wkx": "^0.5.0", }, @@ -234,8 +252,8 @@ "@types/joi": "^17.2.3", "@types/node": "^17.0.45", "@types/uuid": "^8.3.4", - "config-schema": "*", - "database": "*", + "config-schema": "workspace:*", + "database": "workspace:*", "dotenv": "10.0.0", "esbuild": "^0.25.3", "jest": "27.5.1", @@ -245,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", }, @@ -274,9 +293,9 @@ "apollo-server-testing": "2.25.2", "await-semaphore": "0.1.3", "class-validator": "^0.13.2", - "config-schema": "*", + "config-schema": "workspace:*", "cors": "2.8.5", - "database": "*", + "database": "workspace:*", "decimal.js-light": "^2.5.1", "dotenv": "10.0.0", "express": "^4.17.21", @@ -297,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", }, @@ -401,7 +420,6 @@ "name": "shared", "version": "1.0.0", "dependencies": { - "database": "*", "esbuild": "^0.25.2", "log4js": "^6.9.1", "zod": "^3.25.61", @@ -409,7 +427,7 @@ "devDependencies": { "@biomejs/biome": "2.0.0", "@types/node": "^17.0.21", - "typescript": "^5.8.3", + "typescript": "^4.9.5", }, }, }, @@ -924,29 +942,29 @@ "@swc-node/sourcemap-support": ["@swc-node/sourcemap-support@0.5.1", "", { "dependencies": { "source-map-support": "^0.5.21", "tslib": "^2.6.3" } }, "sha512-JxIvIo/Hrpv0JCHSyRpetAdQ6lB27oFYhv0PKCNf1g2gUXOjpeR1exrXccRxLMuAV5WAmGFBwRnNOJqN38+qtg=="], - "@swc/cli": ["@swc/cli@0.7.3", "", { "dependencies": { "@swc/counter": "^0.1.3", "@xhmikosr/bin-wrapper": "^13.0.5", "commander": "^8.3.0", "fast-glob": "^3.2.5", "minimatch": "^9.0.3", "piscina": "^4.3.1", "semver": "^7.3.8", "slash": "3.0.0", "source-map": "^0.7.3" }, "peerDependencies": { "@swc/core": "^1.2.66", "chokidar": "^4.0.1" }, "optionalPeers": ["chokidar"], "bin": { "swc": "bin/swc.js", "swcx": "bin/swcx.js", "spack": "bin/spack.js" } }, "sha512-rnVXNnlURjdOuPaBIwZ3TmBA44BF/eP0j154LanlgPEYfau74ige7cpKlKkZr1IBqMOG99lAnYNxQipDWA3hdg=="], + "@swc/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": ["@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/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-darwin-arm64": ["@swc/core-darwin-arm64@1.11.24", "", { "os": "darwin", "cpu": "arm64" }, "sha512-dhtVj0PC1APOF4fl5qT2neGjRLgHAAYfiVP8poJelhzhB/318bO+QCFWAiimcDoyMgpCXOhTp757gnoJJrheWA=="], + "@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.12.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HihKfeitjZU2ab94Zf893sxzFryLKX0TweGsNXXOLNtkSMLw50auuYfpRM0BOL9/uXXtuCWgRIF6P030SAX5xQ=="], - "@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.11.24", "", { "os": "darwin", "cpu": "x64" }, "sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ=="], + "@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.12.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-meYCXHyYb6RDdu2N5PNAf0EelyxPBFhRcVo4kBFLuvuNb0m6EUg///VWy8MUMXq9/s9uzGS9kJVXXdRdr/d6FA=="], - "@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-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-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.11.24", "", { "os": "linux", "cpu": "arm64" }, "sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg=="], + "@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-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.11.24", "", { "os": "linux", "cpu": "arm64" }, "sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw=="], + "@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.12.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-wE5jmFi5cEQyLy8WmCWmNwfKETrnzy2D8YNi/xpYWpLPWqPhcelpa6tswkfYlbsMmmOh7hQNoTba1QdGu0jvHQ=="], - "@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-x64-gnu": ["@swc/core-linux-x64-gnu@1.12.4", "", { "os": "linux", "cpu": "x64" }, "sha512-6S50Xd/7ePjEwrXyHMxpKTZ+KBrgUwMA8hQPbArUOwH4S5vHBr51heL0iXbUkppn1bkSr0J0IbOove5hzn+iqQ=="], - "@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.11.24", "", { "os": "linux", "cpu": "x64" }, "sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw=="], + "@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.11.24", "", { "os": "win32", "cpu": "arm64" }, "sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ=="], + "@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.11.24", "", { "os": "win32", "cpu": "ia32" }, "sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ=="], + "@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.11.24", "", { "os": "win32", "cpu": "x64" }, "sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w=="], + "@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=="], @@ -954,7 +972,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=="], @@ -1570,6 +1588,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=="], @@ -1634,7 +1654,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=="], @@ -3126,7 +3146,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=="], @@ -3178,7 +3198,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=="], @@ -3376,7 +3396,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=="], @@ -3652,20 +3672,16 @@ "concurrently/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - "config-schema/typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], - "css-select/domhandler": ["domhandler@4.3.1", "", { "dependencies": { "domelementtype": "^2.2.0" } }, "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ=="], "css-select/domutils": ["domutils@2.8.0", "", { "dependencies": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", "domhandler": "^4.2.0" } }, "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A=="], "cssstyle/rrweb-cssom": ["rrweb-cssom@0.8.0", "", {}, "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw=="], - "database/@swc/cli": ["@swc/cli@0.7.7", "", { "dependencies": { "@swc/counter": "^0.1.3", "@xhmikosr/bin-wrapper": "^13.0.5", "commander": "^8.3.0", "fast-glob": "^3.2.5", "minimatch": "^9.0.3", "piscina": "^4.3.1", "semver": "^7.3.8", "slash": "3.0.0", "source-map": "^0.7.3" }, "peerDependencies": { "@swc/core": "^1.2.66", "chokidar": "^4.0.1" }, "optionalPeers": ["chokidar"], "bin": { "swc": "bin/swc.js", "swcx": "bin/swcx.js", "spack": "bin/spack.js" } }, "sha512-j4yYm9bx3pxWofaJKX1BFwj/3ngUDynN4UIQ2Xd2h0h/7Gt7zkReBTpDN7g5S13mgAYxacaTHTOUsz18097E8w=="], - - "database/@swc/core": ["@swc/core@1.12.4", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.23" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.12.4", "@swc/core-darwin-x64": "1.12.4", "@swc/core-linux-arm-gnueabihf": "1.12.4", "@swc/core-linux-arm64-gnu": "1.12.4", "@swc/core-linux-arm64-musl": "1.12.4", "@swc/core-linux-x64-gnu": "1.12.4", "@swc/core-linux-x64-musl": "1.12.4", "@swc/core-win32-arm64-msvc": "1.12.4", "@swc/core-win32-ia32-msvc": "1.12.4", "@swc/core-win32-x64-msvc": "1.12.4" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" }, "optionalPeers": ["@swc/helpers"] }, "sha512-hn30ebV4njAn0NAUM+3a0qCF+MJgqTNSrfA/hUAbC6TVjOQy2OYGQwkUvCu/V7S2+rZxrUsTpKOnZ7qqECZV9Q=="], - "database/@types/node": ["@types/node@18.19.96", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-PzBvgsZ7YdFs/Kng1BSW8IGv68/SPcOxYYhT7luxD7QyzIhFS1xPTpfK3K9eHBa7hVwlW+z8nN0mOd515yaduQ=="], + "database/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=="], @@ -3678,8 +3694,6 @@ "dht-node/ts-jest": ["ts-jest@27.1.4", "", { "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", "jest-util": "^27.0.0", "json5": "2.x", "lodash.memoize": "4.x", "make-error": "1.x", "semver": "7.x", "yargs-parser": "20.x" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", "@types/jest": "^27.0.0", "babel-jest": ">=27.0.0 <28", "jest": "^27.0.0", "typescript": ">=3.8 <5.0" }, "optionalPeers": ["@babel/core", "@types/jest", "babel-jest"], "bin": { "ts-jest": "cli.js" } }, "sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ=="], - "dht-node/tsx": ["tsx@4.19.4", "", { "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q=="], - "dht-rpc/sodium-universal": ["sodium-universal@5.0.1", "", { "dependencies": { "sodium-native": "^5.0.1" }, "peerDependencies": { "sodium-javascript": "~0.8.0" }, "optionalPeers": ["sodium-javascript"] }, "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q=="], "domexception/webidl-conversions": ["webidl-conversions@5.0.0", "", {}, "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA=="], @@ -3722,6 +3736,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=="], @@ -3766,6 +3782,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=="], @@ -3880,8 +3898,6 @@ "send/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], - "shared/typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], - "simple-update-notifier/semver": ["semver@7.0.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A=="], "sodium-secretstream/sodium-universal": ["sodium-universal@5.0.1", "", { "dependencies": { "sodium-native": "^5.0.1" }, "peerDependencies": { "sodium-javascript": "~0.8.0" }, "optionalPeers": ["sodium-javascript"] }, "sha512-rv+aH+tnKB5H0MAc2UadHShLMslpJsc4wjdnHRtiSIEYpOetCgu8MS4ExQRia+GL/MK3uuCyZPeEsi+J3h+Q+Q=="], @@ -3934,8 +3950,16 @@ "test-exclude/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "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=="], @@ -4000,8 +4024,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=="], @@ -4086,31 +4108,7 @@ "css-select/domutils/dom-serializer": ["dom-serializer@1.4.1", "", { "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", "entities": "^2.0.0" } }, "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag=="], - "database/@swc/cli/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="], - - "database/@swc/cli/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "database/@swc/core/@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.12.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HihKfeitjZU2ab94Zf893sxzFryLKX0TweGsNXXOLNtkSMLw50auuYfpRM0BOL9/uXXtuCWgRIF6P030SAX5xQ=="], - - "database/@swc/core/@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.12.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-meYCXHyYb6RDdu2N5PNAf0EelyxPBFhRcVo4kBFLuvuNb0m6EUg///VWy8MUMXq9/s9uzGS9kJVXXdRdr/d6FA=="], - - "database/@swc/core/@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.12.4", "", { "os": "linux", "cpu": "arm" }, "sha512-szfDbf7mE8V64of0q/LSqbk+em+T+TD3uqnH40Z7Qu/aL8vi5CHgyLjWG2SLkLLpyjgkAUF6AKrupgnBYcC2NA=="], - - "database/@swc/core/@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.12.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-n0IY76w+Scx8m3HIVRvLkoResuwsQgjDfAk9bxn99dq4leQO+mE0fkPl0Yw/1BIsPh+kxGfopIJH9zsZ1Z2YrA=="], - - "database/@swc/core/@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.12.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-wE5jmFi5cEQyLy8WmCWmNwfKETrnzy2D8YNi/xpYWpLPWqPhcelpa6tswkfYlbsMmmOh7hQNoTba1QdGu0jvHQ=="], - - "database/@swc/core/@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.12.4", "", { "os": "linux", "cpu": "x64" }, "sha512-6S50Xd/7ePjEwrXyHMxpKTZ+KBrgUwMA8hQPbArUOwH4S5vHBr51heL0iXbUkppn1bkSr0J0IbOove5hzn+iqQ=="], - - "database/@swc/core/@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.12.4", "", { "os": "linux", "cpu": "x64" }, "sha512-hbYRyaHhC13vYKuGG5BrAG5fjjWEQFfQetuFp/4QKEoXDzdnabJoixxWTQACDL3m0JW32nJ+gUzsYIPtFYkwXg=="], - - "database/@swc/core/@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.12.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-e6EbfjPL8GA/bb1lc9Omtxjlz+1ThTsAuBsy4Q3Kpbuh6B3jclg8KzxU/6t91v23wG593mieTyR5f3Pr7X3AWw=="], - - "database/@swc/core/@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.12.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-RG2FzmllBTUf4EksANlIvLckcBrLZEA0t13LIa6L213UZKQfEuDNHezqESgoVhJMg2S/tWauitATOCFgZNSmjg=="], - - "database/@swc/core/@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.12.4", "", { "os": "win32", "cpu": "x64" }, "sha512-oRHKnZlR83zaMeVUCmHENa4j5uNRAWbmEpjYbzRcfC45LPFNWKGWGAGERLx0u87XMUtTGqnVYxnBTHN/rzDHOw=="], - - "database/@swc/core/@swc/types": ["@swc/types@0.1.23", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw=="], + "database/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=="], @@ -4136,6 +4134,8 @@ "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=="], @@ -4146,6 +4146,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=="], @@ -4164,6 +4166,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=="], @@ -4362,8 +4366,6 @@ "css-select/domutils/dom-serializer/entities": ["entities@2.2.0", "", {}, "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="], - "database/@swc/cli/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - "database/vitest/@vitest/mocker/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], "database/vitest/@vitest/spy/tinyspy": ["tinyspy@4.0.3", "", {}, "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A=="], @@ -4436,8 +4438,6 @@ "chokidar-cli/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="], - "database/@swc/cli/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "js-beautify/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], diff --git a/config-schema/package.json b/config-schema/package.json index 17afc7977..c3a6a2b1d 100644 --- a/config-schema/package.json +++ b/config-schema/package.json @@ -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", @@ -27,7 +27,7 @@ "@biomejs/biome": "2.0.0", "@types/node": "^17.0.21", "jest": "27.2.4", - "typescript": "^5.8.3" + "typescript": "^4.9.5" }, "dependencies": { "esbuild": "^0.25.2", diff --git a/shared/bunfig.toml b/core/bunfig.toml similarity index 100% rename from shared/bunfig.toml rename to core/bunfig.toml diff --git a/core/package.json b/core/package.json new file mode 100644 index 000000000..26ed4e13b --- /dev/null +++ b/core/package.json @@ -0,0 +1,40 @@ +{ + "name": "core", + "version": "2.6.0", + "description": "Gradido Core Code, High-Level Shared Code, with dependencies onto 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" + } +} diff --git a/shared/src/config/const.ts b/core/src/config/const.ts similarity index 100% rename from shared/src/config/const.ts rename to core/src/config/const.ts diff --git a/core/src/index.ts b/core/src/index.ts new file mode 100644 index 000000000..0cd6afc7d --- /dev/null +++ b/core/src/index.ts @@ -0,0 +1 @@ +export * from './schema' \ No newline at end of file diff --git a/core/src/schema/index.ts b/core/src/schema/index.ts new file mode 100644 index 000000000..6c1cda831 --- /dev/null +++ b/core/src/schema/index.ts @@ -0,0 +1,4 @@ +import { LOG4JS_BASE_CATEGORY_NAME } from '../config/const' + +export const LOG_CATEGORY_SCHEMA_ALIAS = `${LOG4JS_BASE_CATEGORY_NAME}.schema` +export * from './user.schema' \ No newline at end of file diff --git a/core/src/schema/user.schema.test.ts b/core/src/schema/user.schema.test.ts new file mode 100644 index 000000000..e8faf5abe --- /dev/null +++ b/core/src/schema/user.schema.test.ts @@ -0,0 +1,68 @@ +import { validateAlias } from './user.schema' +import { getLogger } from '../../../config-schema/test/testSetup.bun' +import { LOG_CATEGORY_SCHEMA_ALIAS } from '.' +import { describe, it, expect, beforeEach, mock, jest } from 'bun:test' +import { aliasExists } from 'database' + +const logger = getLogger(`${LOG_CATEGORY_SCHEMA_ALIAS}.alias`) + +mock.module('database', () => ({ + aliasExists: jest.fn(), +})) +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) + }) + }) + }) +}) diff --git a/core/src/schema/user.schema.ts b/core/src/schema/user.schema.ts new file mode 100644 index 000000000..85d3774d0 --- /dev/null +++ b/core/src/schema/user.schema.ts @@ -0,0 +1,27 @@ +import { ZodError } from 'zod' +import { getLogger } from 'log4js' +import { LOG_CATEGORY_SCHEMA_ALIAS } from '.' +import { aliasExists } from 'database' +import { aliasSchema } from 'shared' + +const logger = getLogger(`${LOG_CATEGORY_SCHEMA_ALIAS}.alias`) + +export async function validateAlias(alias: string): Promise { + 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).issues) + throw new Error((err as ZodError).issues[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 +} diff --git a/core/tsconfig.json b/core/tsconfig.json new file mode 100644 index 000000000..75b686340 --- /dev/null +++ b/core/tsconfig.json @@ -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"], +} diff --git a/core/turbo.json b/core/turbo.json new file mode 100644 index 000000000..9f85ac803 --- /dev/null +++ b/core/turbo.json @@ -0,0 +1,24 @@ +{ + "extends": ["//"], + "tasks": { + "lint": { + }, + "lint:fix": { + }, + "test": { + "dependsOn": ["config-schema#build"] + }, + "typecheck": { + }, + "dev": { + "dependsOn": ["database#build", "config-schema#build"], + "persistent": true, + "cache": false + }, + "build": { + "dependsOn": ["^build"], + "outputs": ["build/**"], + "cache": true + } + } +} \ No newline at end of file diff --git a/database/package.json b/database/package.json index e62875f4a..cd1ad5f87 100644 --- a/database/package.json +++ b/database/package.json @@ -13,7 +13,7 @@ "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", @@ -58,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.20.3", - "typeorm": "^0.3.22", + "typeorm": "^0.3.25", "uuid": "^8.3.2", "wkx": "^0.5.0" }, diff --git a/database/src/AppDatabase.ts b/database/src/AppDatabase.ts index f10c095bb..f995a176a 100644 --- a/database/src/AppDatabase.ts +++ b/database/src/AppDatabase.ts @@ -4,7 +4,7 @@ import { Migration, entities } from './entity' import { getLogger } from 'log4js' import { latestDbVersion } from '.' import { CONFIG } from './config' -import { LOG4JS_BASE_CATEGORY_NAME, MIGRATIONS_TABLE } from './config/const' +import { LOG4JS_BASE_CATEGORY_NAME } from './config/const' const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.AppDatabase`) diff --git a/database/src/seeds/factory/user.ts b/database/src/seeds/factory/user.ts index fbca53490..412d0088a 100644 --- a/database/src/seeds/factory/user.ts +++ b/database/src/seeds/factory/user.ts @@ -2,12 +2,13 @@ import { UserInterface } from '../users/UserInterface' import { User, UserContact } from '../../entity' import { generateRandomNumber, generateRandomNumericString } from '../utils' import { v4 } from 'uuid' +import { UserContactType, OptInType, PasswordEncryptionType } from 'shared' export const userFactory = async (user: UserInterface): Promise => { let dbUserContact = new UserContact() dbUserContact.email = user.email ?? '' - dbUserContact.type = 'email' //UserContactType.USER_CONTACT_EMAIL + dbUserContact.type = UserContactType.USER_CONTACT_EMAIL let dbUser = new User() dbUser.firstName = user.firstName ?? '' @@ -21,11 +22,10 @@ export const userFactory = async (user: UserInterface): Promise => { if (user.emailChecked) { dbUserContact.emailVerificationCode = generateRandomNumericString(64) - dbUserContact.emailOptInTypeId = 1 //OptInType.EMAIL_OPT_IN_REGISTER + dbUserContact.emailOptInTypeId = OptInType.EMAIL_OPT_IN_REGISTER dbUserContact.emailChecked = true dbUser.password = generateRandomNumber() - // TODO: think where to put enums - dbUser.passwordEncryptionType = 2 //PasswordEncryptionType.GRADIDO_ID + dbUser.passwordEncryptionType = PasswordEncryptionType.GRADIDO_ID } // TODO: improve with cascade dbUser = await dbUser.save() diff --git a/dht-node/package.json b/dht-node/package.json index a973f7087..8a5cd4462 100644 --- a/dht-node/package.json +++ b/dht-node/package.json @@ -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" }, diff --git a/dht-node/test/helpers.ts b/dht-node/test/helpers.ts index 52b847b4c..5978f7bb9 100644 --- a/dht-node/test/helpers.ts +++ b/dht-node/test/helpers.ts @@ -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) + } } } diff --git a/dht-node/tsconfig.json b/dht-node/tsconfig.json index d87ceed66..9628b7c41 100644 --- a/dht-node/tsconfig.json +++ b/dht-node/tsconfig.json @@ -54,7 +54,7 @@ "typeRoots": [ /* List of folders to include type definitions from. */ "src/dht_node/@types", "node_modules/@types", - // "../node_modules/@types" + "../node_modules/@types" ], // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ diff --git a/federation/package.json b/federation/package.json index 3e15b8e14..f2bae7d73 100644 --- a/federation/package.json +++ b/federation/package.json @@ -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" }, diff --git a/federation/test/helpers.ts b/federation/test/helpers.ts index c8523fe7e..7c6280a44 100644 --- a/federation/test/helpers.ts +++ b/federation/test/helpers.ts @@ -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) + } } } diff --git a/frontend/package.json b/frontend/package.json index 7e122a237..4dbace5c1 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -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", diff --git a/package.json b/package.json index 5f9d212c7..350091046 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "admin", "backend", "config-schema", + "core", "database", "dht-node", "federation", diff --git a/scripts/release.sh b/scripts/release.sh index caa8d517c..45221398d 100755 --- a/scripts/release.sh +++ b/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} diff --git a/shared/package.json b/shared/package.json index 279c27ee9..5c8ba7195 100644 --- a/shared/package.json +++ b/shared/package.json @@ -1,7 +1,7 @@ { "name": "shared", - "version": "1.0.0", - "description": "Gradido Shared Code", + "version": "2.6.0", + "description": "Gradido Shared Code, Low-Level Shared Code, without dependencies onto other modules", "main": "./build/index.js", "types": "./src/index.ts", "exports": { @@ -26,10 +26,9 @@ "devDependencies": { "@biomejs/biome": "2.0.0", "@types/node": "^17.0.21", - "typescript": "^5.8.3" + "typescript": "^4.9.5" }, "dependencies": { - "database": "*", "esbuild": "^0.25.2", "log4js": "^6.9.1", "zod": "^3.25.61" diff --git a/shared/src/enum/OptInType.ts b/shared/src/enum/OptInType.ts new file mode 100644 index 000000000..1f6300b39 --- /dev/null +++ b/shared/src/enum/OptInType.ts @@ -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) \ No newline at end of file diff --git a/shared/src/enum/PasswordEncryptionType.ts b/shared/src/enum/PasswordEncryptionType.ts new file mode 100644 index 000000000..13b72be0c --- /dev/null +++ b/shared/src/enum/PasswordEncryptionType.ts @@ -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) + diff --git a/shared/src/enum/RoleNames.ts b/shared/src/enum/RoleNames.ts new file mode 100644 index 000000000..fec1f47a1 --- /dev/null +++ b/shared/src/enum/RoleNames.ts @@ -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) diff --git a/shared/src/enum/UserContactType.ts b/shared/src/enum/UserContactType.ts new file mode 100644 index 000000000..c6f1ef03b --- /dev/null +++ b/shared/src/enum/UserContactType.ts @@ -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) diff --git a/shared/src/enum/index.ts b/shared/src/enum/index.ts new file mode 100644 index 000000000..efd722624 --- /dev/null +++ b/shared/src/enum/index.ts @@ -0,0 +1,4 @@ +export * from './RoleNames' +export * from './UserContactType' +export * from './PasswordEncryptionType' +export * from './OptInType' diff --git a/shared/src/index.ts b/shared/src/index.ts index 30612341b..d252da56f 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -1,3 +1,2 @@ -import * as schema from './schema' - -export { schema } \ No newline at end of file +export * from './schema' +export * from './enum' \ No newline at end of file diff --git a/shared/src/schema/index.ts b/shared/src/schema/index.ts index 6c1cda831..b60401cfa 100644 --- a/shared/src/schema/index.ts +++ b/shared/src/schema/index.ts @@ -1,4 +1 @@ -import { LOG4JS_BASE_CATEGORY_NAME } from '../config/const' - -export const LOG_CATEGORY_SCHEMA_ALIAS = `${LOG4JS_BASE_CATEGORY_NAME}.schema` -export * from './user.schema' \ No newline at end of file +export * from './user.schema' diff --git a/shared/src/schema/user.schema.test.ts b/shared/src/schema/user.schema.test.ts index 1b4ae1d9d..f29bb2af5 100644 --- a/shared/src/schema/user.schema.test.ts +++ b/shared/src/schema/user.schema.test.ts @@ -1,10 +1,6 @@ -import { validateAlias } from './user.schema' -import { getLogger } from '../../../config-schema/test/testSetup.bun' -import { LOG_CATEGORY_SCHEMA_ALIAS } from '.' +import { aliasSchema } from './user.schema' import { describe, it, expect, beforeEach, mock, jest } from 'bun:test' -import { aliasExists } from 'database' -const logger = getLogger(`${LOG_CATEGORY_SCHEMA_ALIAS}.alias`) mock.module('database', () => ({ aliasExists: jest.fn(), @@ -15,76 +11,25 @@ describe('validate alias', () => { jest.clearAllMocks() }) - describe('alias too short', () => { - it('throws and logs an error', () => { - expect(validateAlias('Bi')).rejects.toThrowError(new Error('Given alias is too short')) - expect(logger.warn.mock.calls[0]).toEqual([ - 'invalid alias', - 'Bi', - expect.arrayContaining([ - expect.objectContaining({ - code: 'too_small', - minimum: 3, - type: 'string', - inclusive: true, - exact: false, - message: 'Given alias is too short', - path: [], - }), - ]), - ]) - }) - }) - - describe('alias too long', () => { - it('throws and logs an error', () => { - expect(validateAlias('BibiBloxbergHexHexHex')).rejects.toThrowError( - new Error('Given alias is too long'), - ) - expect(logger.warn.mock.calls[0]).toEqual([ - 'invalid alias', - 'BibiBloxbergHexHexHex', - expect.arrayContaining([ - expect.objectContaining({ - code: 'too_big', - maximum: 20, - type: 'string', - inclusive: true, - exact: false, - message: 'Given alias is too long', - path: [], - }), - ]), - ]) - }) - }) - describe('alias contains invalid characters', () => { it('throws and logs an error', () => { - expect(validateAlias('Bibi.Bloxberg')).rejects.toEqual( - new Error('Invalid characters in alias'), - ) - expect(logger.warn.mock.calls[0]).toEqual([ - 'invalid alias', - 'Bibi.Bloxberg', + expect(() => aliasSchema.parse('Bibi.Bloxberg')).toThrowError(expect.objectContaining( expect.arrayContaining([ expect.objectContaining({ - validation: 'regex', - code: 'invalid_string', + origin: 'string', + code: 'invalid_format', + format: 'regex', message: 'Invalid characters in alias', path: [], - }), - ]), - ]) + }) + ]) + )) }) }) describe('alias is a reserved word', () => { it('throws and logs an error', () => { - expect(validateAlias('admin')).rejects.toEqual(new Error('Given alias is not allowed')) - expect(logger.warn.mock.calls[0]).toEqual([ - 'invalid alias', - 'admin', + expect(() => aliasSchema.parse('admin')).toThrowError(expect.objectContaining( expect.arrayContaining([ expect.objectContaining({ code: 'custom', @@ -92,16 +37,13 @@ describe('validate alias', () => { path: [], }), ]), - ]) + )) }) }) describe('alias is a reserved word with uppercase characters', () => { it('throws and logs an error', () => { - expect(validateAlias('Admin')).rejects.toEqual(new Error('Given alias is not allowed')) - expect(logger.warn.mock.calls[0]).toEqual([ - 'invalid alias', - 'Admin', + expect(() => aliasSchema.parse('Admin')).toThrowError(expect.objectContaining( expect.arrayContaining([ expect.objectContaining({ code: 'custom', @@ -109,72 +51,40 @@ describe('validate alias', () => { path: [], }), ]), - ]) + )) }) }) describe('hyphens and underscore', () => { describe('alias starts with underscore', () => { it('throws and logs an error', () => { - expect(validateAlias('_bibi')).rejects.toEqual( - new Error('Invalid characters in alias'), - ) - expect(logger.warn.mock.calls[0]).toEqual([ - 'invalid alias', - '_bibi', + expect(() => aliasSchema.parse('_bibi')).toThrowError(expect.objectContaining( expect.arrayContaining([ expect.objectContaining({ - validation: 'regex', - code: 'invalid_string', + origin: 'string', + code: 'invalid_format', + format: 'regex', message: 'Invalid characters in alias', path: [], - }), - ]), - ]) + }) + ]) + )) }) }) describe('alias contains two following hyphens', () => { it('throws and logs an error', () => { - expect(validateAlias('bi--bi')).rejects.toEqual( - new Error('Invalid characters in alias'), - ) - expect(logger.warn.mock.calls[0]).toEqual([ - 'invalid alias', - 'bi--bi', + expect(() => aliasSchema.parse('bi--bi')).toThrowError(expect.objectContaining( expect.arrayContaining([ expect.objectContaining({ - validation: 'regex', - code: 'invalid_string', + origin: 'string', + code: 'invalid_format', + format: 'regex', message: 'Invalid characters in alias', path: [], - }), - ]), - ]) - }) - }) - }) -// TODO: add integration test with real database to test the query, maybe move query - describe('test against existing alias in database', () => { - describe('alias exists in database', () => { - it('throws and logs an error', () => { - (aliasExists as jest.Mock).mockResolvedValue(true) - expect(validateAlias('b-b')).rejects.toEqual(new Error('Given alias is already in use')) - expect(logger.warn.mock.calls[0]).toEqual(['alias already in use', 'b-b']) - }) - }) - -/* describe('alias exists in database with in lower-case', () => { - it('throws and logs an error', () => { - expect(validateAlias('b-B')).rejects.toEqual(new Error('Given alias is already in use')) - expect(logger.warn.mock.calls[0]).toEqual(['alias already in use', 'b-B']) - }) - }) -*/ - describe('valid alias', () => { - it('resolves to true', async () => { - (aliasExists as jest.Mock).mockResolvedValue(false) - expect(validateAlias('bibi')).resolves.toEqual(true) + }) + ]) + )) }) }) }) diff --git a/shared/src/schema/user.schema.ts b/shared/src/schema/user.schema.ts index 23dbe3b85..4a1c51d74 100644 --- a/shared/src/schema/user.schema.ts +++ b/shared/src/schema/user.schema.ts @@ -1,10 +1,6 @@ -import { z } from 'zod' -import { getLogger } from 'log4js' -import { LOG_CATEGORY_SCHEMA_ALIAS } from '.' -import { aliasExists } from 'database' +import { string } from 'zod' export const VALID_ALIAS_REGEX = /^(?=.{3,20}$)[a-zA-Z0-9]+(?:[_-][a-zA-Z0-9]+?)*$/ -const logger = getLogger(`${LOG_CATEGORY_SCHEMA_ALIAS}.alias`) const RESERVED_ALIAS = [ 'admin', @@ -24,31 +20,10 @@ const RESERVED_ALIAS = [ 'var', ] -export const aliasSchema = z - .string() +export const aliasSchema = string() .min(3, 'Given alias is too short') .max(20, 'Given alias is too long') .regex(VALID_ALIAS_REGEX, 'Invalid characters in alias') .refine((val) => !RESERVED_ALIAS.includes(val.toLowerCase()), { message: 'Given alias is not allowed', }) - -export const validateAlias = async (alias: string): Promise => { - try { - aliasSchema.parse(alias) - } catch (err) { - if (err instanceof z.ZodError) { - // throw only first error, but log all errors - logger.warn('invalid alias', alias, err.errors) - throw new Error(err.errors[0].message) - } - throw err - } - - if (await aliasExists(alias)) { - logger.warn('alias already in use', alias) - throw new Error('Given alias is already in use') - } - - return true -} diff --git a/yarn.lock b/yarn.lock index 6366943f1..36e413b72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4573,7 +4573,7 @@ browserslist@^4.24.0, browserslist@^4.24.4: node-releases "^2.0.19" update-browserslist-db "^1.1.1" -bs-logger@0.x: +bs-logger@0.x, bs-logger@^0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== @@ -5377,6 +5377,11 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== +dedent@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.6.0.tgz#79d52d6389b1ffa67d2bcef59ba51847a9d503b2" + integrity sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA== + deep-eql@^5.0.1: version "5.0.2" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" @@ -5698,7 +5703,7 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -ejs@^3.1.6: +ejs@^3.1.10, ejs@^3.1.6: version "3.1.10" resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== @@ -6550,7 +6555,7 @@ fast-glob@^3.2.11, fast-glob@^3.2.12, fast-glob@^3.2.5, fast-glob@^3.2.9, fast-g merge2 "^1.3.0" micromatch "^4.0.8" -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -8915,7 +8920,7 @@ lodash.get@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== -lodash.memoize@4.x: +lodash.memoize@4.x, lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== @@ -9067,7 +9072,7 @@ make-dir@^4.0.0: dependencies: semver "^7.5.3" -make-error@1.x, make-error@^1.1.1: +make-error@1.x, make-error@^1.1.1, make-error@^1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -10869,6 +10874,11 @@ semver@^6.1.0, semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== +semver@^7.7.2: + version "7.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== + semver@~7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" @@ -11946,6 +11956,21 @@ ts-jest@27.1.4: semver "7.x" yargs-parser "20.x" +ts-jest@29.4.0: + version "29.4.0" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.4.0.tgz#bef0ee98d94c83670af7462a1617bf2367a83740" + integrity sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q== + 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" + ts-mysql-migrate@^1.0.2: version "1.1.2" resolved "https://registry.yarnpkg.com/ts-mysql-migrate/-/ts-mysql-migrate-1.1.2.tgz#6f280f4684cb95440ffa7254b926b494badb8cf3" @@ -12106,6 +12131,11 @@ type-fest@^4.26.1, type-fest@^4.8.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.40.1.tgz#d78a09f08dd1081a434dd377967650cfd565401d" integrity sha512-9YvLNnORDpI+vghLU/Nf+zSv0kL47KbVJ1o3sKgoTefl6i+zebxbiDQWoe/oWWqPhIgQdRZRT1KA9sCPL810SA== +type-fest@^4.41.0: + version "4.41.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" + integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== + type-graphql@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/type-graphql/-/type-graphql-1.1.1.tgz#dc0710d961713b92d3fee927981fa43bf71667a4" @@ -12189,10 +12219,10 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typeorm@^0.3.22: - version "0.3.22" - resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.22.tgz#74b56af4a495b6c8eda887dc9aa4670782b991ff" - integrity sha512-P/Tsz3UpJ9+K0oryC0twK5PO27zejLYYwMsE8SISfZc1lVHX+ajigiOyWsKbuXpEFMjD9z7UjLzY3+ElVOMMDA== +typeorm@^0.3.25: + version "0.3.25" + resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.25.tgz#9a416f93cda0f612b20f8450e03d6b0e11b467fb" + integrity sha512-fTKDFzWXKwAaBdEMU4k661seZewbNYET4r1J/z3Jwf+eAvlzMVpTLKAVcAzg75WwQk7GDmtsmkZ5MfkmXCiFWg== dependencies: "@sqltools/formatter" "^1.2.5" ansis "^3.17.0" @@ -12200,6 +12230,7 @@ typeorm@^0.3.22: 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" @@ -12213,11 +12244,6 @@ typescript@^4.9.5: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== -typescript@^5.8.3: - version "5.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" - integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== - uc.micro@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee"