diff --git a/autoadmin-ws-server/package.json b/autoadmin-ws-server/package.json index cc7f403f6..9b90c693f 100644 --- a/autoadmin-ws-server/package.json +++ b/autoadmin-ws-server/package.json @@ -1,31 +1,31 @@ { - "name": "rocketadmin-ws-server", - "version": "1.0.0", - "type": "module", - "license": "UNLICENSED", - "scripts": { - "dev": "tsx watch src/index.ts", - "build": "tsc", - "start": "node dist/index.js", - "lint": "biome check src/", - "lint:fix": "biome check --write src/" - }, - "dependencies": { - "@hono/node-server": "^1.19.9", - "hono": "^4.11.7", - "jsonwebtoken": "^9.0.3", - "lru-cache": "^11.2.5", - "nanoid": "^5.1.6", - "pino": "^10.3.0", - "ws": "^8.19.0", - "zod": "^4.3.6" - }, - "devDependencies": { - "@biomejs/biome": "2.3.13", - "@types/jsonwebtoken": "^9.0.10", - "@types/node": "^22.10.2", - "@types/ws": "^8.18.1", - "tsx": "^4.21.0", - "typescript": "^5.9.3" - } + "name": "rocketadmin-ws-server", + "version": "1.0.0", + "type": "module", + "license": "UNLICENSED", + "scripts": { + "dev": "tsx watch src/index.ts", + "build": "tsc", + "start": "node dist/index.js", + "lint": "biome check src/", + "lint:fix": "biome check --write src/" + }, + "dependencies": { + "@hono/node-server": "^1.19.9", + "hono": "^4.11.7", + "jsonwebtoken": "^9.0.3", + "lru-cache": "^11.2.5", + "nanoid": "^5.1.6", + "pino": "^10.3.0", + "ws": "^8.19.0", + "zod": "^4.3.6" + }, + "devDependencies": { + "@biomejs/biome": "2.3.13", + "@types/jsonwebtoken": "^9.0.10", + "@types/node": "^22.10.2", + "@types/ws": "^8.18.1", + "tsx": "^4.21.0", + "typescript": "^5.9.3" + } } diff --git a/autoadmin-ws-server/src/utils/jwt.ts b/autoadmin-ws-server/src/utils/jwt.ts index 94ef5dd77..8d99e24ad 100644 --- a/autoadmin-ws-server/src/utils/jwt.ts +++ b/autoadmin-ws-server/src/utils/jwt.ts @@ -13,8 +13,7 @@ export function signToken(connectionToken: string): Promise { if (err) { return reject(err); } - if (!token) { - + if (!token) { return reject(new Error('Failed to sign token')); } return resolve(token); diff --git a/autoadmin-ws-server/tsconfig.json b/autoadmin-ws-server/tsconfig.json index 45b6b79fa..6e2bea645 100644 --- a/autoadmin-ws-server/tsconfig.json +++ b/autoadmin-ws-server/tsconfig.json @@ -1,24 +1,24 @@ { - "compilerOptions": { - "target": "ES2022", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "lib": ["ES2022"], - "outDir": "./dist", - "rootDir": "./src", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "declaration": true, - "declarationMap": true, - "sourceMap": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "lib": ["ES2022"], + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] } diff --git a/backend/src/authorization/auth-with-api.middleware.ts b/backend/src/authorization/auth-with-api.middleware.ts index e00346931..404e63ff5 100644 --- a/backend/src/authorization/auth-with-api.middleware.ts +++ b/backend/src/authorization/auth-with-api.middleware.ts @@ -8,17 +8,17 @@ import { UnauthorizedException, } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { UserEntity } from '../entities/user/user.entity.js'; -import { Repository } from 'typeorm'; +import Sentry from '@sentry/minimal'; import { Request, Response } from 'express'; -import { Constants } from '../helpers/constants/constants.js'; -import { isObjectEmpty } from '../helpers/is-object-empty.js'; +import jwt from 'jsonwebtoken'; +import { Repository } from 'typeorm'; import { JwtScopesEnum } from '../entities/user/enums/jwt-scopes.enum.js'; +import { UserEntity } from '../entities/user/user.entity.js'; +import { EncryptionAlgorithmEnum } from '../enums/encryption-algorithm.enum.js'; import { Messages } from '../exceptions/text/messages.js'; -import jwt from 'jsonwebtoken'; -import Sentry from '@sentry/minimal'; +import { Constants } from '../helpers/constants/constants.js'; import { Encryptor } from '../helpers/encryption/encryptor.js'; -import { EncryptionAlgorithmEnum } from '../enums/encryption-algorithm.enum.js'; +import { isObjectEmpty } from '../helpers/is-object-empty.js'; import { IRequestWithCognitoInfo } from './cognito-decoded.interface.js'; @Injectable() diff --git a/backend/src/authorization/auth.middleware.ts b/backend/src/authorization/auth.middleware.ts index d3cbd61da..a66afc854 100644 --- a/backend/src/authorization/auth.middleware.ts +++ b/backend/src/authorization/auth.middleware.ts @@ -7,16 +7,16 @@ import { UnauthorizedException, } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import Sentry from '@sentry/minimal'; import { Response } from 'express'; import jwt from 'jsonwebtoken'; import { Repository } from 'typeorm'; import { LogOutEntity } from '../entities/log-out/log-out.entity.js'; +import { JwtScopesEnum } from '../entities/user/enums/jwt-scopes.enum.js'; import { UserEntity } from '../entities/user/user.entity.js'; import { Messages } from '../exceptions/text/messages.js'; -import { isObjectEmpty } from '../helpers/index.js'; import { Constants } from '../helpers/constants/constants.js'; -import Sentry from '@sentry/minimal'; -import { JwtScopesEnum } from '../entities/user/enums/jwt-scopes.enum.js'; +import { isObjectEmpty } from '../helpers/index.js'; import { IRequestWithCognitoInfo } from './cognito-decoded.interface.js'; @Injectable() diff --git a/backend/src/entities/agent/repository/custom-agent-repository-extension.ts b/backend/src/entities/agent/repository/custom-agent-repository-extension.ts index 37c72341d..c9d82035f 100644 --- a/backend/src/entities/agent/repository/custom-agent-repository-extension.ts +++ b/backend/src/entities/agent/repository/custom-agent-repository-extension.ts @@ -1,76 +1,76 @@ +import { ConnectionTypeTestEnum } from '@rocketadmin/shared-code/dist/src/shared/enums/connection-types-enum.js'; import { nanoid } from 'nanoid'; import { ConnectionEntity } from '../../connection/connection.entity.js'; import { AgentEntity } from '../agent.entity.js'; -import { ConnectionTypeTestEnum } from '@rocketadmin/shared-code/dist/src/shared/enums/connection-types-enum.js'; export const customAgentRepositoryExtension = { - async saveNewAgent(agent: AgentEntity): Promise { - return await this.save(agent); - }, + async saveNewAgent(agent: AgentEntity): Promise { + return await this.save(agent); + }, - async createNewAgentForConnectionAndReturnToken(connection: ConnectionEntity): Promise { - const newAgent = await this.createNewAgentForConnection(connection); - return newAgent.token; - }, + async createNewAgentForConnectionAndReturnToken(connection: ConnectionEntity): Promise { + const newAgent = await this.createNewAgentForConnection(connection); + return newAgent.token; + }, - async createNewAgentForConnection(connection: ConnectionEntity): Promise { - const agent = new AgentEntity(); - let token = nanoid(64); - if (process.env.NODE_ENV !== 'test') { - agent.token = token; - } else { - token = this.getTestAgentToken(connection.type); - agent.token = token; - } - agent.connection = connection; - const savedAgent = await this.save(agent); - savedAgent.token = token; - return savedAgent; - }, + async createNewAgentForConnection(connection: ConnectionEntity): Promise { + const agent = new AgentEntity(); + let token = nanoid(64); + if (process.env.NODE_ENV !== 'test') { + agent.token = token; + } else { + token = this.getTestAgentToken(connection.type); + agent.token = token; + } + agent.connection = connection; + const savedAgent = await this.save(agent); + savedAgent.token = token; + return savedAgent; + }, - async renewOrCreateConnectionToken(connectionId: string): Promise { - const agentQb = this.createQueryBuilder('agent') - .leftJoinAndSelect('agent.connection', 'connection') - .andWhere('connection.id = :connectionId', { connectionId: connectionId }); - const foundAgent = await agentQb.getOne(); - if (!foundAgent) { - const connectionQb = this.manager - .getRepository(ConnectionEntity) - .createQueryBuilder('connection') - .andWhere('connection.id = :connectionId', { connectionId: connectionId }); - const foundConnection = await connectionQb.getOne(); - return await this.createNewAgentForConnectionAndReturnToken(foundConnection); - } else { - const newToken = nanoid(64); - foundAgent.token = newToken; - await this.save(foundAgent); - return newToken; - } - }, + async renewOrCreateConnectionToken(connectionId: string): Promise { + const agentQb = this.createQueryBuilder('agent') + .leftJoinAndSelect('agent.connection', 'connection') + .andWhere('connection.id = :connectionId', { connectionId: connectionId }); + const foundAgent = await agentQb.getOne(); + if (!foundAgent) { + const connectionQb = this.manager + .getRepository(ConnectionEntity) + .createQueryBuilder('connection') + .andWhere('connection.id = :connectionId', { connectionId: connectionId }); + const foundConnection = await connectionQb.getOne(); + return await this.createNewAgentForConnectionAndReturnToken(foundConnection); + } else { + const newToken = nanoid(64); + foundAgent.token = newToken; + await this.save(foundAgent); + return newToken; + } + }, - getTestAgentToken(connectionType: ConnectionTypeTestEnum): string { - if (process.env.NODE_ENV !== 'test') throw new Error('Test agent token can only be used in test environment'); - switch (connectionType) { - case ConnectionTypeTestEnum.agent_oracledb: - return 'ORACLE-TEST-AGENT-TOKEN'; - case ConnectionTypeTestEnum.agent_mssql: - return 'MSSQL-TEST-AGENT-TOKEN'; - case ConnectionTypeTestEnum.agent_mysql: - return 'MYSQL-TEST-AGENT-TOKEN'; - case ConnectionTypeTestEnum.agent_postgres: - return 'POSTGRES-TEST-AGENT-TOKEN'; - case ConnectionTypeTestEnum.agent_ibmdb2: - return 'IBMDB2-TEST-AGENT-TOKEN'; - case ConnectionTypeTestEnum.agent_mongodb: - return 'MONGODB-TEST-AGENT-TOKEN'; - case ConnectionTypeTestEnum.agent_redis: - return 'REDIS-TEST-AGENT-TOKEN'; - case ConnectionTypeTestEnum.agent_cassandra: - return 'CASSANDRA-TEST-AGENT-TOKEN'; - case ConnectionTypeTestEnum.agent_clickhouse: - return 'CLICKHOUSE-TEST-AGENT-TOKEN'; - default: - throw new Error(`Unsupported connection type for test agent token: ${connectionType}`); - } - }, + getTestAgentToken(connectionType: ConnectionTypeTestEnum): string { + if (process.env.NODE_ENV !== 'test') throw new Error('Test agent token can only be used in test environment'); + switch (connectionType) { + case ConnectionTypeTestEnum.agent_oracledb: + return 'ORACLE-TEST-AGENT-TOKEN'; + case ConnectionTypeTestEnum.agent_mssql: + return 'MSSQL-TEST-AGENT-TOKEN'; + case ConnectionTypeTestEnum.agent_mysql: + return 'MYSQL-TEST-AGENT-TOKEN'; + case ConnectionTypeTestEnum.agent_postgres: + return 'POSTGRES-TEST-AGENT-TOKEN'; + case ConnectionTypeTestEnum.agent_ibmdb2: + return 'IBMDB2-TEST-AGENT-TOKEN'; + case ConnectionTypeTestEnum.agent_mongodb: + return 'MONGODB-TEST-AGENT-TOKEN'; + case ConnectionTypeTestEnum.agent_redis: + return 'REDIS-TEST-AGENT-TOKEN'; + case ConnectionTypeTestEnum.agent_cassandra: + return 'CASSANDRA-TEST-AGENT-TOKEN'; + case ConnectionTypeTestEnum.agent_clickhouse: + return 'CLICKHOUSE-TEST-AGENT-TOKEN'; + default: + throw new Error(`Unsupported connection type for test agent token: ${connectionType}`); + } + }, }; diff --git a/backend/src/entities/ai/ai.service.ts b/backend/src/entities/ai/ai.service.ts index cdd67ac99..9376dad32 100644 --- a/backend/src/entities/ai/ai.service.ts +++ b/backend/src/entities/ai/ai.service.ts @@ -1,11 +1,11 @@ import { Injectable } from '@nestjs/common'; -import { WidgetTypeEnum } from '../../enums/widget-type.enum.js'; +import { AICoreService, AIProviderType, cleanAIJsonResponse } from '../../ai-core/index.js'; import { QueryOrderingEnum } from '../../enums/query-ordering.enum.js'; +import { WidgetTypeEnum } from '../../enums/widget-type.enum.js'; import { checkFieldAutoincrement } from '../../helpers/check-field-autoincrement.js'; +import { TableSettingsEntity } from '../table-settings/common-table-settings/table-settings.entity.js'; import { TableWidgetEntity } from '../widget/table-widget.entity.js'; import { TableInformation } from './ai-data-entities/types/ai-module-types.js'; -import { TableSettingsEntity } from '../table-settings/common-table-settings/table-settings.entity.js'; -import { AICoreService, AIProviderType, cleanAIJsonResponse } from '../../ai-core/index.js'; interface AIGeneratedWidgetParams { options?: Array<{ value: string; label: string; background_color?: string }>; diff --git a/backend/src/entities/shared-jobs/shared-jobs.service.ts b/backend/src/entities/shared-jobs/shared-jobs.service.ts index 4f9ab5453..d43627ead 100644 --- a/backend/src/entities/shared-jobs/shared-jobs.service.ts +++ b/backend/src/entities/shared-jobs/shared-jobs.service.ts @@ -13,10 +13,10 @@ import { isTest } from '../../helpers/app/is-test.js'; import { ValidationHelper } from '../../helpers/validators/validation-helper.js'; import { AiService } from '../ai/ai.service.js'; import { ConnectionEntity } from '../connection/connection.entity.js'; +import { TableSettingsEntity } from '../table-settings/common-table-settings/table-settings.entity.js'; import { buildEmptyTableSettings } from '../table-settings/common-table-settings/utils/build-empty-table-settings.js'; import { buildNewTableSettingsEntity } from '../table-settings/common-table-settings/utils/build-new-table-settings-entity.js'; import { TableWidgetEntity } from '../widget/table-widget.entity.js'; -import { TableSettingsEntity } from '../table-settings/common-table-settings/table-settings.entity.js'; @Injectable() export class SharedJobsService { diff --git a/backend/src/entities/table-settings/common-table-settings/table-settings.entity.ts b/backend/src/entities/table-settings/common-table-settings/table-settings.entity.ts index c4bc4f39f..680bbb33e 100644 --- a/backend/src/entities/table-settings/common-table-settings/table-settings.entity.ts +++ b/backend/src/entities/table-settings/common-table-settings/table-settings.entity.ts @@ -11,11 +11,11 @@ import { Unique, UpdateDateColumn, } from 'typeorm'; +import { QueryOrderingEnum } from '../../../enums/query-ordering.enum.js'; import { ConnectionEntity } from '../../connection/connection.entity.js'; import { CustomFieldsEntity } from '../../custom-field/custom-fields.entity.js'; import { TableActionEntity } from '../../table-actions/table-actions-module/table-action.entity.js'; import { TableWidgetEntity } from '../../widget/table-widget.entity.js'; -import { QueryOrderingEnum } from '../../../enums/query-ordering.enum.js'; @Entity('tableSettings') @Unique(['connection_id', 'table_name']) diff --git a/backend/test/ava-tests/non-saas-tests/non-saas-company-info-e2e.test.ts b/backend/test/ava-tests/non-saas-tests/non-saas-company-info-e2e.test.ts index 342795530..e8fb849c1 100644 --- a/backend/test/ava-tests/non-saas-tests/non-saas-company-info-e2e.test.ts +++ b/backend/test/ava-tests/non-saas-tests/non-saas-company-info-e2e.test.ts @@ -1,26 +1,27 @@ /* eslint-disable prefer-const */ /* eslint-disable @typescript-eslint/no-unused-vars */ + +import { faker } from '@faker-js/faker'; import { INestApplication, ValidationPipe } from '@nestjs/common'; import { Test } from '@nestjs/testing'; import test from 'ava'; +import { ValidationError } from 'class-validator'; import cookieParser from 'cookie-parser'; +import { nanoid } from 'nanoid'; import request from 'supertest'; import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; +import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; +import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; +import { Messages } from '../../../src/exceptions/text/messages.js'; +import { Cacher } from '../../../src/helpers/cache/cacher.js'; +import { Constants } from '../../../src/helpers/constants/constants.js'; import { DatabaseModule } from '../../../src/shared/database/database.module.js'; import { DatabaseService } from '../../../src/shared/database/database.service.js'; import { MockFactory } from '../../mock.factory.js'; -import { TestUtils } from '../../utils/test.utils.js'; import { setSaasEnvVariable } from '../../utils/set-saas-env-variable.js'; -import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; +import { TestUtils } from '../../utils/test.utils.js'; import { createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions } from '../../utils/user-with-different-permissions-utils.js'; -import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; -import { ValidationError } from 'class-validator'; -import { faker } from '@faker-js/faker'; -import { nanoid } from 'nanoid'; -import { Constants } from '../../../src/helpers/constants/constants.js'; -import { Messages } from '../../../src/exceptions/text/messages.js'; -import { Cacher } from '../../../src/helpers/cache/cacher.js'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; const _mockFactory = new MockFactory(); let app: INestApplication; @@ -28,635 +29,636 @@ let _testUtils: TestUtils; let currentTest: string; test.before(async () => { - setSaasEnvVariable(); - const moduleFixture = await Test.createTestingModule({ - imports: [ApplicationModule, DatabaseModule], - providers: [DatabaseService, TestUtils], - }).compile(); - app = moduleFixture.createNestApplication() as any; - _testUtils = moduleFixture.get(TestUtils); - - app.use(cookieParser()); - app.useGlobalFilters(new AllExceptionsFilter(app.get(WinstonLogger))); - app.useGlobalPipes( - new ValidationPipe({ - exceptionFactory(validationErrors: ValidationError[] = []) { - return new ValidationException(validationErrors); - }, - }), - ); - await app.init(); - app.getHttpServer().listen(0); + setSaasEnvVariable(); + const moduleFixture = await Test.createTestingModule({ + imports: [ApplicationModule, DatabaseModule], + providers: [DatabaseService, TestUtils], + }).compile(); + app = moduleFixture.createNestApplication() as any; + _testUtils = moduleFixture.get(TestUtils); + + app.use(cookieParser()); + app.useGlobalFilters(new AllExceptionsFilter(app.get(WinstonLogger))); + app.useGlobalPipes( + new ValidationPipe({ + exceptionFactory(validationErrors: ValidationError[] = []) { + return new ValidationException(validationErrors); + }, + }), + ); + await app.init(); + app.getHttpServer().listen(0); }); test.after(async () => { - try { - await Cacher.clearAllCache(); - await app.close(); - } catch (e) { - console.error('After tests error ' + e); - } + try { + await Cacher.clearAllCache(); + await app.close(); + } catch (e) { + console.error('After tests error ' + e); + } }); currentTest = 'GET /company/my'; test.serial(`${currentTest} should return found company info for user`, async (t) => { - try { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my') - .set('Content-Type', 'application/json') - .set('Cookie', simpleUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - t.is(Object.hasOwn(foundCompanyInfoRO, 'id'), true); - t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); - t.is(Object.keys(foundCompanyInfoRO).length, 8); - } catch (error) { - console.error(error); - } + try { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my') + .set('Content-Type', 'application/json') + .set('Cookie', simpleUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + t.is(Object.hasOwn(foundCompanyInfoRO, 'id'), true); + t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); + t.is(Object.keys(foundCompanyInfoRO).length, 8); + } catch (error) { + console.error(error); + } }); currentTest = 'GET /company/my/full'; test.serial(`${currentTest} should return full found company info for company admin user`, async (t) => { - try { - console.log('\nCALLED CONNECTIONS CREATION\n'); - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken }, - } = testData; - - console.log('\nCALLED GET COMPANY INFO\n'); - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - // console.log('🚀 ~ test.serial ~ foundCompanyInfoRO:', foundCompanyInfoRO); - // console.log( - // `🚀 ~ file: non-saas-company-info-e2e.test.ts:87 ~ test ~ foundCompanyInfoRO: \n\n - // ${JSON.stringify(foundCompanyInfoRO)} - // \n\n - // ` - // ); - - t.is(foundCompanyInfo.status, 200); - t.is(Object.hasOwn(foundCompanyInfoRO, 'id'), true); - t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); - t.is(Object.keys(foundCompanyInfoRO).length, 10); - t.is(Object.hasOwn(foundCompanyInfoRO, 'connections'), true); - t.is(foundCompanyInfoRO.connections.length > 0, true); - t.is(Object.hasOwn(foundCompanyInfoRO, 'invitations'), true); - t.is(foundCompanyInfoRO.invitations.length, 0); - t.is(Object.keys(foundCompanyInfoRO.connections[0]).length, 7); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'id'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'title'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'createdAt'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'updatedAt'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'author'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'groups'), true); - t.is(foundCompanyInfoRO.connections[0].groups.length > 0, true); - t.is(Object.keys(foundCompanyInfoRO.connections[0].groups[0]).length, 4); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'id'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'title'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'isMain'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'users'), true); - t.is(foundCompanyInfoRO.connections[0].groups[0].users.length > 0, true); - t.is(Object.keys(foundCompanyInfoRO.connections[0].groups[0].users[0]).length, 9); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'id'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'email'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'role'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'createdAt'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'password'), false); - } catch (error) { - console.error(error); - throw error; - } + try { + console.log('\nCALLED CONNECTIONS CREATION\n'); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken }, + } = testData; + + console.log('\nCALLED GET COMPANY INFO\n'); + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + // console.log('🚀 ~ test.serial ~ foundCompanyInfoRO:', foundCompanyInfoRO); + // console.log( + // `🚀 ~ file: non-saas-company-info-e2e.test.ts:87 ~ test ~ foundCompanyInfoRO: \n\n + // ${JSON.stringify(foundCompanyInfoRO)} + // \n\n + // ` + // ); + + t.is(foundCompanyInfo.status, 200); + t.is(Object.hasOwn(foundCompanyInfoRO, 'id'), true); + t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); + t.is(Object.keys(foundCompanyInfoRO).length, 10); + t.is(Object.hasOwn(foundCompanyInfoRO, 'connections'), true); + t.is(foundCompanyInfoRO.connections.length > 0, true); + t.is(Object.hasOwn(foundCompanyInfoRO, 'invitations'), true); + t.is(foundCompanyInfoRO.invitations.length, 0); + t.is(Object.keys(foundCompanyInfoRO.connections[0]).length, 7); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'id'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'title'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'createdAt'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'updatedAt'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'author'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'groups'), true); + t.is(foundCompanyInfoRO.connections[0].groups.length > 0, true); + t.is(Object.keys(foundCompanyInfoRO.connections[0].groups[0]).length, 4); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'id'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'title'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'isMain'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'users'), true); + t.is(foundCompanyInfoRO.connections[0].groups[0].users.length > 0, true); + t.is(Object.keys(foundCompanyInfoRO.connections[0].groups[0].users[0]).length, 9); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'id'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'email'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'role'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'createdAt'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'password'), false); + } catch (error) { + console.error(error); + throw error; + } }); test.serial(`${currentTest} should return found company info for non-admin user`, async (t) => { - try { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', simpleUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - t.is(foundCompanyInfo.status, 200); - t.is(Object.hasOwn(foundCompanyInfoRO, 'id'), true); - t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); - t.is(Object.keys(foundCompanyInfoRO).length, 8); - } catch (error) { - console.error(error); - throw error; - } + try { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', simpleUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + t.is(foundCompanyInfo.status, 200); + t.is(Object.hasOwn(foundCompanyInfoRO, 'id'), true); + t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); + t.is(Object.keys(foundCompanyInfoRO).length, 8); + } catch (error) { + console.error(error); + throw error; + } }); currentTest = 'GET /company/my/email'; test.serial(`${currentTest} should return found company infos for admin user`, async (t) => { - try { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get(`/company/my/email/${testData.users.adminUserEmail}`) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - t.is(foundCompanyInfo.status, 200); - t.is(Array.isArray(foundCompanyInfoRO), true); - t.is(foundCompanyInfoRO.length, 1); - t.is(Object.hasOwn(foundCompanyInfoRO[0], 'id'), true); - } catch (error) { - console.error(error); - throw error; - } + try { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get(`/company/my/email/${testData.users.adminUserEmail}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + t.is(foundCompanyInfo.status, 200); + t.is(Array.isArray(foundCompanyInfoRO), true); + t.is(foundCompanyInfoRO.length, 1); + t.is(Object.hasOwn(foundCompanyInfoRO[0], 'id'), true); + } catch (error) { + console.error(error); + throw error; + } }); test.serial(`${currentTest} should return found company infos for non-admin user`, async (t) => { - try { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get(`/company/my/email/${testData.users.simpleUserEmail}`) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - t.is(foundCompanyInfo.status, 200); - t.is(Array.isArray(foundCompanyInfoRO), true); - t.is(foundCompanyInfoRO.length, 1); - t.is(Object.hasOwn(foundCompanyInfoRO[0], 'id'), true); - } catch (error) { - console.error(error); - throw error; - } + try { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get(`/company/my/email/${testData.users.simpleUserEmail}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + t.is(foundCompanyInfo.status, 200); + t.is(Array.isArray(foundCompanyInfoRO), true); + t.is(foundCompanyInfoRO.length, 1); + t.is(Object.hasOwn(foundCompanyInfoRO[0], 'id'), true); + } catch (error) { + console.error(error); + throw error; + } }); currentTest = 'POST /company/remove'; test.serial(`${currentTest} should remove user from company`, async (t) => { - try { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - t.is(foundCompanyInfo.status, 200); - - const allGroupsInResult = foundCompanyInfoRO.connections.flatMap((connection) => connection.groups); - const allUsersInResult = allGroupsInResult.flatMap((group) => group.users); - const foundSimpleUserInResult = allUsersInResult.find((user) => user.email === simpleUserEmail.toLowerCase()); - - t.is(foundSimpleUserInResult.email, simpleUserEmail.toLowerCase()); - - const removeUserFromCompanyResult = await request(app.getHttpServer()) - .delete(`/company/${foundCompanyInfoRO.id}/user/${foundSimpleUserInResult.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const removeUserFromCompany = JSON.parse(removeUserFromCompanyResult.text); - - t.is(removeUserFromCompanyResult.status, 200); - t.is(removeUserFromCompany.success, true); - - const foundCompanyInfoAfterUserDeletion = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoROAfterUserDeletion = JSON.parse(foundCompanyInfoAfterUserDeletion.text); - - const allGroupsInResultAfterUserDeletion = foundCompanyInfoROAfterUserDeletion.connections - .flatMap((connection) => connection.groups); - const allUsersInResultAfterUserDeletion = allGroupsInResultAfterUserDeletion.flatMap((group) => group.users); - const foundSimpleUserInResultAfterUserDeletion = !!allUsersInResultAfterUserDeletion.find( - (user) => user.email === simpleUserEmail, - ); - - t.is(foundSimpleUserInResultAfterUserDeletion, false); - } catch (error) { - console.error(error); - throw error; - } + try { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + t.is(foundCompanyInfo.status, 200); + + const allGroupsInResult = foundCompanyInfoRO.connections.flatMap((connection) => connection.groups); + const allUsersInResult = allGroupsInResult.flatMap((group) => group.users); + const foundSimpleUserInResult = allUsersInResult.find((user) => user.email === simpleUserEmail.toLowerCase()); + + t.is(foundSimpleUserInResult.email, simpleUserEmail.toLowerCase()); + + const removeUserFromCompanyResult = await request(app.getHttpServer()) + .delete(`/company/${foundCompanyInfoRO.id}/user/${foundSimpleUserInResult.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const removeUserFromCompany = JSON.parse(removeUserFromCompanyResult.text); + + t.is(removeUserFromCompanyResult.status, 200); + t.is(removeUserFromCompany.success, true); + + const foundCompanyInfoAfterUserDeletion = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoROAfterUserDeletion = JSON.parse(foundCompanyInfoAfterUserDeletion.text); + + const allGroupsInResultAfterUserDeletion = foundCompanyInfoROAfterUserDeletion.connections.flatMap( + (connection) => connection.groups, + ); + const allUsersInResultAfterUserDeletion = allGroupsInResultAfterUserDeletion.flatMap((group) => group.users); + const foundSimpleUserInResultAfterUserDeletion = !!allUsersInResultAfterUserDeletion.find( + (user) => user.email === simpleUserEmail, + ); + + t.is(foundSimpleUserInResultAfterUserDeletion, false); + } catch (error) { + console.error(error); + throw error; + } }); currentTest = 'PUT invitation/revoke/:slug'; test.serial(`${currentTest} should remove user invitation from company`, async (t) => { - try { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - t.is(foundCompanyInfoRO.invitations.length, 0); - - const allGroupsInResult = foundCompanyInfoRO.connections.flatMap((connection) => connection.groups); - const allUsersInResult = allGroupsInResult.flatMap((group) => group.users); - const foundSimpleUserInResult = allUsersInResult.find((user) => user.email === simpleUserEmail.toLowerCase()); - - const _removeUserFromCompanyResult = await request(app.getHttpServer()) - .delete(`/company/${foundCompanyInfoRO.id}/user/${foundSimpleUserInResult.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const invitationRequestBody = { - companyId: foundCompanyInfoRO.id, - email: simpleUserEmail, - role: 'USER', - groupId: foundCompanyInfoRO.connections[0].groups[0].id, - }; - - const invitationResult = await request(app.getHttpServer()) - .put(`/company/user/${foundCompanyInfoRO.id}`) - .send(invitationRequestBody) - .set('Cookie', adminUserToken) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - console.log(invitationResult.text); - t.is(invitationResult.status, 200); - - const foundCompanyInfoWithInvitation = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoWithInvitationRO = JSON.parse(foundCompanyInfoWithInvitation.text); - t.is(foundCompanyInfoWithInvitationRO.invitations.length, 1); - - const deleteInvitationResult = await request(app.getHttpServer()) - .put(`/company/invitation/revoke/${foundCompanyInfoRO.id}`) - .send({ - email: simpleUserEmail, - }) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(deleteInvitationResult.status, 200); - - const foundCompanyInfoAfterInvitationDeletion = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoROAfterInvitationDeletion = JSON.parse(foundCompanyInfoAfterInvitationDeletion.text); - t.is(foundCompanyInfoROAfterInvitationDeletion.invitations.length, 0); - } catch (error) { - console.error(error); - throw error; - } + try { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + t.is(foundCompanyInfoRO.invitations.length, 0); + + const allGroupsInResult = foundCompanyInfoRO.connections.flatMap((connection) => connection.groups); + const allUsersInResult = allGroupsInResult.flatMap((group) => group.users); + const foundSimpleUserInResult = allUsersInResult.find((user) => user.email === simpleUserEmail.toLowerCase()); + + const _removeUserFromCompanyResult = await request(app.getHttpServer()) + .delete(`/company/${foundCompanyInfoRO.id}/user/${foundSimpleUserInResult.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const invitationRequestBody = { + companyId: foundCompanyInfoRO.id, + email: simpleUserEmail, + role: 'USER', + groupId: foundCompanyInfoRO.connections[0].groups[0].id, + }; + + const invitationResult = await request(app.getHttpServer()) + .put(`/company/user/${foundCompanyInfoRO.id}`) + .send(invitationRequestBody) + .set('Cookie', adminUserToken) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + console.log(invitationResult.text); + t.is(invitationResult.status, 200); + + const foundCompanyInfoWithInvitation = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoWithInvitationRO = JSON.parse(foundCompanyInfoWithInvitation.text); + t.is(foundCompanyInfoWithInvitationRO.invitations.length, 1); + + const deleteInvitationResult = await request(app.getHttpServer()) + .put(`/company/invitation/revoke/${foundCompanyInfoRO.id}`) + .send({ + email: simpleUserEmail, + }) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(deleteInvitationResult.status, 200); + + const foundCompanyInfoAfterInvitationDeletion = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoROAfterInvitationDeletion = JSON.parse(foundCompanyInfoAfterInvitationDeletion.text); + t.is(foundCompanyInfoROAfterInvitationDeletion.invitations.length, 0); + } catch (error) { + console.error(error); + throw error; + } }); currentTest = 'PUT company/name/:slug'; test.serial(`${currentTest} should update company name`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); - - const newName = `${faker.company.name()}_${nanoid(5)}`; - - const updateCompanyNameResult = await request(app.getHttpServer()) - .put(`/company/name/${foundCompanyInfoRO.id}`) - .send({ - name: newName, - }) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - t.is(updateCompanyNameResult.status, 200); - - const foundCompanyInfoAfterUpdate = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - const foundCompanyInfoROAfterUpdate = JSON.parse(foundCompanyInfoAfterUpdate.text); - t.is(Object.hasOwn(foundCompanyInfoROAfterUpdate, 'name'), true); - t.is(foundCompanyInfoROAfterUpdate.name, newName); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); + + const newName = `${faker.company.name()}_${nanoid(5)}`; + + const updateCompanyNameResult = await request(app.getHttpServer()) + .put(`/company/name/${foundCompanyInfoRO.id}`) + .send({ + name: newName, + }) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + t.is(updateCompanyNameResult.status, 200); + + const foundCompanyInfoAfterUpdate = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + const foundCompanyInfoROAfterUpdate = JSON.parse(foundCompanyInfoAfterUpdate.text); + t.is(Object.hasOwn(foundCompanyInfoROAfterUpdate, 'name'), true); + t.is(foundCompanyInfoROAfterUpdate.name, newName); }); currentTest = 'GET company/name/:companyId'; test.serial(`${currentTest} should return company name`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - const foundCompanyName = await request(app.getHttpServer()) - .get(`/company/name/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - t.is(foundCompanyName.status, 200); - const foundCompanyNameRO = JSON.parse(foundCompanyName.text); - t.is(Object.hasOwn(foundCompanyNameRO, 'name'), true); - t.is(foundCompanyNameRO.name, foundCompanyInfoRO.name); - t.pass(); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + const foundCompanyName = await request(app.getHttpServer()) + .get(`/company/name/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + t.is(foundCompanyName.status, 200); + const foundCompanyNameRO = JSON.parse(foundCompanyName.text); + t.is(Object.hasOwn(foundCompanyNameRO, 'name'), true); + t.is(foundCompanyNameRO.name, foundCompanyInfoRO.name); + t.pass(); }); currentTest = `PUT company/users/roles/:companyId`; test.serial(`${currentTest} should update user roles in company`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - const usersInCompany = await request(app.getHttpServer()) - .get(`/company/users/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(usersInCompany.status, 200); - const usersInCompanyRO = JSON.parse(usersInCompany.text); - - t.is(usersInCompanyRO.length > 0, true); - - const foundNonAdminUser = usersInCompanyRO.find((user) => user.role === 'USER'); - t.is(!!foundNonAdminUser, true); - - const updateUserRoleRequest = { - users: [ - { - userId: foundNonAdminUser.id, - role: 'ADMIN', - }, - ], - }; - - const updateUserRoleResult = await request(app.getHttpServer()) - .put(`/company/users/roles/${foundCompanyInfoRO.id}`) - .send(updateUserRoleRequest) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(updateUserRoleResult.status, 200); - const updateUserRoleResultRO = JSON.parse(updateUserRoleResult.text); - t.is(updateUserRoleResultRO.success, true); - - const usersInCompanyAfterUpdate = await request(app.getHttpServer()) - .get(`/company/users/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(usersInCompanyAfterUpdate.status, 200); - const usersInCompanyROAfterUpdate = JSON.parse(usersInCompanyAfterUpdate.text); - - t.is(usersInCompanyRO.length > 0, true); - - const foundUserAfterUpdate = usersInCompanyROAfterUpdate.find((user) => user.id === foundNonAdminUser.id); - t.is(foundUserAfterUpdate.role, 'ADMIN'); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + const usersInCompany = await request(app.getHttpServer()) + .get(`/company/users/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(usersInCompany.status, 200); + const usersInCompanyRO = JSON.parse(usersInCompany.text); + + t.is(usersInCompanyRO.length > 0, true); + + const foundNonAdminUser = usersInCompanyRO.find((user) => user.role === 'USER'); + t.is(!!foundNonAdminUser, true); + + const updateUserRoleRequest = { + users: [ + { + userId: foundNonAdminUser.id, + role: 'ADMIN', + }, + ], + }; + + const updateUserRoleResult = await request(app.getHttpServer()) + .put(`/company/users/roles/${foundCompanyInfoRO.id}`) + .send(updateUserRoleRequest) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(updateUserRoleResult.status, 200); + const updateUserRoleResultRO = JSON.parse(updateUserRoleResult.text); + t.is(updateUserRoleResultRO.success, true); + + const usersInCompanyAfterUpdate = await request(app.getHttpServer()) + .get(`/company/users/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(usersInCompanyAfterUpdate.status, 200); + const usersInCompanyROAfterUpdate = JSON.parse(usersInCompanyAfterUpdate.text); + + t.is(usersInCompanyRO.length > 0, true); + + const foundUserAfterUpdate = usersInCompanyROAfterUpdate.find((user) => user.id === foundNonAdminUser.id); + t.is(foundUserAfterUpdate.role, 'ADMIN'); }); currentTest = `PUT company/2fa/:companyId`; test.skip(`${currentTest} should enable 2fa for company`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - - const foundCompanyRo = JSON.parse(foundCompanyInfo.text); - t.is(Object.hasOwn(foundCompanyRo, 'is2faEnabled'), true); - t.is(foundCompanyRo.is2faEnabled, false); - - const requestBody = { - is2faEnabled: true, - }; - const enable2faResult = await request(app.getHttpServer()) - .put(`/company/2fa/${foundCompanyRo.id}`) - .send(requestBody) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(enable2faResult.status, 200); - - const foundCompanyInfoAfterUpdate = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfoAfterUpdate.status, 200); - const foundCompanyRoAfterUpdate = JSON.parse(foundCompanyInfoAfterUpdate.text); - t.is(Object.hasOwn(foundCompanyRoAfterUpdate, 'is2faEnabled'), true); - t.is(foundCompanyRoAfterUpdate.is2faEnabled, true); - - // user should not be able to use endpoints that require 2fa after login - - const userLoginInfo = { - email: simpleUserEmail, - password: simpleUserPassword, - }; - - const loginUserResponse = await request(app.getHttpServer()) - .post('/user/login/') - .send(userLoginInfo) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - if (loginUserResponse.status > 201) { - console.info('loginUserResponse.text -> ', loginUserResponse.text); - } - - const newSimpleUserToken = `${Constants.JWT_COOKIE_KEY_NAME}=${TestUtils.getJwtTokenFromResponse(loginUserResponse)}`; - const connectionsResult = await request(app.getHttpServer()) - .get('/connections') - .set('Content-Type', 'application/json') - .set('Cookie', newSimpleUserToken) - .set('Accept', 'application/json'); - - t.is(connectionsResult.status, 401); - - const connectionsResultsObject = JSON.parse(connectionsResult.text); - t.is(connectionsResultsObject.message, Messages.TWO_FA_REQUIRED); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + + const foundCompanyRo = JSON.parse(foundCompanyInfo.text); + t.is(Object.hasOwn(foundCompanyRo, 'is2faEnabled'), true); + t.is(foundCompanyRo.is2faEnabled, false); + + const requestBody = { + is2faEnabled: true, + }; + const enable2faResult = await request(app.getHttpServer()) + .put(`/company/2fa/${foundCompanyRo.id}`) + .send(requestBody) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(enable2faResult.status, 200); + + const foundCompanyInfoAfterUpdate = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfoAfterUpdate.status, 200); + const foundCompanyRoAfterUpdate = JSON.parse(foundCompanyInfoAfterUpdate.text); + t.is(Object.hasOwn(foundCompanyRoAfterUpdate, 'is2faEnabled'), true); + t.is(foundCompanyRoAfterUpdate.is2faEnabled, true); + + // user should not be able to use endpoints that require 2fa after login + + const userLoginInfo = { + email: simpleUserEmail, + password: simpleUserPassword, + }; + + const loginUserResponse = await request(app.getHttpServer()) + .post('/user/login/') + .send(userLoginInfo) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + if (loginUserResponse.status > 201) { + console.info('loginUserResponse.text -> ', loginUserResponse.text); + } + + const newSimpleUserToken = `${Constants.JWT_COOKIE_KEY_NAME}=${TestUtils.getJwtTokenFromResponse(loginUserResponse)}`; + const connectionsResult = await request(app.getHttpServer()) + .get('/connections') + .set('Content-Type', 'application/json') + .set('Cookie', newSimpleUserToken) + .set('Accept', 'application/json'); + + t.is(connectionsResult.status, 401); + + const connectionsResultsObject = JSON.parse(connectionsResult.text); + t.is(connectionsResultsObject.message, Messages.TWO_FA_REQUIRED); }); currentTest = `DELETE company`; test.serial(`${currentTest} should delete company`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, - } = testData; - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - - const deleteCompanyResult = await request(app.getHttpServer()) - .delete(`/company/my`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(deleteCompanyResult.status, 200); - const deleteCompanyResultRO = JSON.parse(deleteCompanyResult.text); - t.is(deleteCompanyResultRO.success, true); - - const foundCompanyInfoAfterDelete = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfoAfterDelete.status, 401); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, + } = testData; + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + + const deleteCompanyResult = await request(app.getHttpServer()) + .delete(`/company/my`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(deleteCompanyResult.status, 200); + const deleteCompanyResultRO = JSON.parse(deleteCompanyResult.text); + t.is(deleteCompanyResultRO.success, true); + + const foundCompanyInfoAfterDelete = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfoAfterDelete.status, 401); }); diff --git a/backend/test/ava-tests/non-saas-tests/non-saas-table-postgres-schema-e2e.test.ts b/backend/test/ava-tests/non-saas-tests/non-saas-table-postgres-schema-e2e.test.ts index 2d28e37ea..ab6071f06 100644 --- a/backend/test/ava-tests/non-saas-tests/non-saas-table-postgres-schema-e2e.test.ts +++ b/backend/test/ava-tests/non-saas-tests/non-saas-table-postgres-schema-e2e.test.ts @@ -4,11 +4,14 @@ import { faker } from '@faker-js/faker'; import { INestApplication, ValidationPipe } from '@nestjs/common'; import { Test } from '@nestjs/testing'; import test from 'ava'; +import { ValidationError } from 'class-validator'; import cookieParser from 'cookie-parser'; import request from 'supertest'; import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; import { LogOperationTypeEnum, QueryOrderingEnum } from '../../../src/enums/index.js'; import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; +import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; import { Messages } from '../../../src/exceptions/text/messages.js'; import { Cacher } from '../../../src/helpers/cache/cacher.js'; import { Constants } from '../../../src/helpers/constants/constants.js'; @@ -19,11 +22,8 @@ import { createTestPostgresTableWithSchema } from '../../utils/create-test-table import { dropTestTables } from '../../utils/drop-test-tables.js'; import { getTestData } from '../../utils/get-test-data.js'; import { registerUserAndReturnUserInfo } from '../../utils/register-user-and-return-user-info.js'; -import { TestUtils } from '../../utils/test.utils.js'; import { setSaasEnvVariable } from '../../utils/set-saas-env-variable.js'; -import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; -import { ValidationError } from 'class-validator'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; +import { TestUtils } from '../../utils/test.utils.js'; const mockFactory = new MockFactory(); let app: INestApplication; diff --git a/backend/test/ava-tests/non-saas-tests/non-saas-user-e2e.test.ts b/backend/test/ava-tests/non-saas-tests/non-saas-user-e2e.test.ts index 070d0256b..83d8bb4a5 100644 --- a/backend/test/ava-tests/non-saas-tests/non-saas-user-e2e.test.ts +++ b/backend/test/ava-tests/non-saas-tests/non-saas-user-e2e.test.ts @@ -1,203 +1,204 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import test from 'ava'; -import { Test } from '@nestjs/testing'; -import { ApplicationModule } from '../../../src/app.module.js'; -import { DatabaseModule } from '../../../src/shared/database/database.module.js'; -import { DatabaseService } from '../../../src/shared/database/database.service.js'; -import { TestUtils } from '../../utils/test.utils.js'; + import { INestApplication, ValidationPipe } from '@nestjs/common'; +import { Test } from '@nestjs/testing'; +import test from 'ava'; +import { ValidationError } from 'class-validator'; +import cookieParser from 'cookie-parser'; import request from 'supertest'; +import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; import { IUserInfo } from '../../../src/entities/user/user.interface.js'; import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; -import cookieParser from 'cookie-parser'; -import { registerUserAndReturnUserInfo } from '../../utils/register-user-and-return-user-info.js'; -import { setSaasEnvVariable } from '../../utils/set-saas-env-variable.js'; import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; -import { ValidationError } from 'class-validator'; import { Cacher } from '../../../src/helpers/cache/cacher.js'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; +import { DatabaseModule } from '../../../src/shared/database/database.module.js'; +import { DatabaseService } from '../../../src/shared/database/database.service.js'; +import { registerUserAndReturnUserInfo } from '../../utils/register-user-and-return-user-info.js'; +import { setSaasEnvVariable } from '../../utils/set-saas-env-variable.js'; +import { TestUtils } from '../../utils/test.utils.js'; let app: INestApplication; let currentTest: string; let _testUtils: TestUtils; test.beforeEach(async () => { - setSaasEnvVariable(); - const moduleFixture = await Test.createTestingModule({ - imports: [ApplicationModule, DatabaseModule], - providers: [DatabaseService, TestUtils], - }).compile(); - app = moduleFixture.createNestApplication(); - _testUtils = moduleFixture.get(TestUtils); - // await testUtils.resetDb(); - app.use(cookieParser()); - app.useGlobalFilters(new AllExceptionsFilter(app.get(WinstonLogger))); - app.useGlobalPipes( - new ValidationPipe({ - exceptionFactory(validationErrors: ValidationError[] = []) { - return new ValidationException(validationErrors); - }, - }), - ); - await app.init(); - app.getHttpServer().listen(0); + setSaasEnvVariable(); + const moduleFixture = await Test.createTestingModule({ + imports: [ApplicationModule, DatabaseModule], + providers: [DatabaseService, TestUtils], + }).compile(); + app = moduleFixture.createNestApplication(); + _testUtils = moduleFixture.get(TestUtils); + // await testUtils.resetDb(); + app.use(cookieParser()); + app.useGlobalFilters(new AllExceptionsFilter(app.get(WinstonLogger))); + app.useGlobalPipes( + new ValidationPipe({ + exceptionFactory(validationErrors: ValidationError[] = []) { + return new ValidationException(validationErrors); + }, + }), + ); + await app.init(); + app.getHttpServer().listen(0); }); test.after(async () => { - try { - await Cacher.clearAllCache(); - await app.close(); - } catch (e) { - console.error('After tests error ' + e); - } + try { + await Cacher.clearAllCache(); + await app.close(); + } catch (e) { + console.error('After tests error ' + e); + } }); currentTest = 'GET /user'; test.serial(`${currentTest} should return user info for this user`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { token } = adminUserRegisterInfo; - - const getUserResult = await request(app.getHttpServer()) - .get('/user') - .set('Content-Type', 'application/json') - .set('Cookie', token) - .set('Accept', 'application/json'); - const getUserRO: IUserInfo = JSON.parse(getUserResult.text); - - t.is(getUserRO.isActive, true); - t.is(getUserRO.email, adminUserRegisterInfo.email); - t.is(Object.hasOwn(getUserRO, 'createdAt'), true); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { token } = adminUserRegisterInfo; + + const getUserResult = await request(app.getHttpServer()) + .get('/user') + .set('Content-Type', 'application/json') + .set('Cookie', token) + .set('Accept', 'application/json'); + const getUserRO: IUserInfo = JSON.parse(getUserResult.text); + + t.is(getUserRO.isActive, true); + t.is(getUserRO.email, adminUserRegisterInfo.email); + t.is(Object.hasOwn(getUserRO, 'createdAt'), true); + t.pass(); }); currentTest = 'DELETE /user'; test.serial(`${currentTest} should return user deletion result`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { token } = adminUserRegisterInfo; - - let getUserResult = await request(app.getHttpServer()) - .get('/user') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - t.is(getUserResult.status, 200); - const deleteUserResult = await request(app.getHttpServer()) - .put('/user/delete/') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const deleteUserRO = JSON.parse(deleteUserResult.text); - t.is(deleteUserRO.email, adminUserRegisterInfo.email); - getUserResult = await request(app.getHttpServer()) - .get('/user') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - t.is(getUserResult.status, 401); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { token } = adminUserRegisterInfo; + + let getUserResult = await request(app.getHttpServer()) + .get('/user') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + t.is(getUserResult.status, 200); + const deleteUserResult = await request(app.getHttpServer()) + .put('/user/delete/') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const deleteUserRO = JSON.parse(deleteUserResult.text); + t.is(deleteUserRO.email, adminUserRegisterInfo.email); + getUserResult = await request(app.getHttpServer()) + .get('/user') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + t.is(getUserResult.status, 401); + t.pass(); }); test.serial(`${currentTest} should return expiration token when user login`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { email, password } = adminUserRegisterInfo; - - const loginUserResult = await request(app.getHttpServer()) - .post('/user/login/') - .send({ email, password }) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const loginUserRO = JSON.parse(loginUserResult.text); - t.is(Object.hasOwn(loginUserRO, 'expires'), true); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { email, password } = adminUserRegisterInfo; + + const loginUserResult = await request(app.getHttpServer()) + .post('/user/login/') + .send({ email, password }) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const loginUserRO = JSON.parse(loginUserResult.text); + t.is(Object.hasOwn(loginUserRO, 'expires'), true); + t.pass(); }); test.serial(`${currentTest} reject authorization when try to login with wrong password`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { email, password } = adminUserRegisterInfo; - - const realPassword = password; - const wrongPassword = 'wrong password'; - const wrongUserLogin = await request(app.getHttpServer()) - .post('/user/login/') - .send({ email, password: wrongPassword }) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - t.is(wrongUserLogin.status, 400); - - const loginUserResult = await request(app.getHttpServer()) - .post('/user/login/') - .send({ email, password: realPassword }) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const loginUserRO = JSON.parse(loginUserResult.text); - t.is(Object.hasOwn(loginUserRO, 'expires'), true); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { email, password } = adminUserRegisterInfo; + + const realPassword = password; + const wrongPassword = 'wrong password'; + const wrongUserLogin = await request(app.getHttpServer()) + .post('/user/login/') + .send({ email, password: wrongPassword }) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + t.is(wrongUserLogin.status, 400); + + const loginUserResult = await request(app.getHttpServer()) + .post('/user/login/') + .send({ email, password: realPassword }) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const loginUserRO = JSON.parse(loginUserResult.text); + t.is(Object.hasOwn(loginUserRO, 'expires'), true); + t.pass(); }); currentTest = 'GET /user/settings'; test.serial(`${currentTest} should return empty user settings when it was not created`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { token } = adminUserRegisterInfo; - - const getUserSettingsResult = await request(app.getHttpServer()) - .get('/user/settings') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const getUserSettingsRO = JSON.parse(getUserSettingsResult.text); - t.is(getUserSettingsResult.status, 200); - t.is(Object.hasOwn(getUserSettingsRO, 'userSettings'), true); - t.is(getUserSettingsRO.userSettings, null); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { token } = adminUserRegisterInfo; + + const getUserSettingsResult = await request(app.getHttpServer()) + .get('/user/settings') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const getUserSettingsRO = JSON.parse(getUserSettingsResult.text); + t.is(getUserSettingsResult.status, 200); + t.is(Object.hasOwn(getUserSettingsRO, 'userSettings'), true); + t.is(getUserSettingsRO.userSettings, null); + t.pass(); }); currentTest = 'POST /user/settings'; test.serial(`${currentTest} should return created user settings`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { token } = adminUserRegisterInfo; - - const settings = JSON.stringify({ test: 'test' }); - - const saveUserSettingsResult = await request(app.getHttpServer()) - .post('/user/settings') - .send({ userSettings: settings }) - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - t.is(saveUserSettingsResult.status, 201); - const saveUserSettingsRO = JSON.parse(saveUserSettingsResult.text); - t.is(Object.hasOwn(saveUserSettingsRO, 'userSettings'), true); - t.is(JSON.parse(saveUserSettingsRO.userSettings).test, 'test'); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { token } = adminUserRegisterInfo; + + const settings = JSON.stringify({ test: 'test' }); + + const saveUserSettingsResult = await request(app.getHttpServer()) + .post('/user/settings') + .send({ userSettings: settings }) + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + t.is(saveUserSettingsResult.status, 201); + const saveUserSettingsRO = JSON.parse(saveUserSettingsResult.text); + t.is(Object.hasOwn(saveUserSettingsRO, 'userSettings'), true); + t.is(JSON.parse(saveUserSettingsRO.userSettings).test, 'test'); + t.pass(); }); test.serial(`${currentTest} should return user settings when it was created`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { token } = adminUserRegisterInfo; - - const settings = JSON.stringify({ test: 'test' }); - - const saveUserSettingsResult = await request(app.getHttpServer()) - .post('/user/settings') - .send({ userSettings: settings }) - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - t.is(saveUserSettingsResult.status, 201); - - const getUserSettingsResult = await request(app.getHttpServer()) - .get('/user/settings') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const getUserSettingsRO = JSON.parse(getUserSettingsResult.text); - t.is(getUserSettingsResult.status, 200); - t.is(Object.hasOwn(getUserSettingsRO, 'userSettings'), true); - t.is(JSON.parse(getUserSettingsRO.userSettings).test, 'test'); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { token } = adminUserRegisterInfo; + + const settings = JSON.stringify({ test: 'test' }); + + const saveUserSettingsResult = await request(app.getHttpServer()) + .post('/user/settings') + .send({ userSettings: settings }) + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + t.is(saveUserSettingsResult.status, 201); + + const getUserSettingsResult = await request(app.getHttpServer()) + .get('/user/settings') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const getUserSettingsRO = JSON.parse(getUserSettingsResult.text); + t.is(getUserSettingsResult.status, 200); + t.is(Object.hasOwn(getUserSettingsRO, 'userSettings'), true); + t.is(JSON.parse(getUserSettingsRO.userSettings).test, 'test'); + t.pass(); }); diff --git a/backend/test/ava-tests/saas-tests/company-info-e2e.test.ts b/backend/test/ava-tests/saas-tests/company-info-e2e.test.ts index 52d7b9211..83517c0de 100644 --- a/backend/test/ava-tests/saas-tests/company-info-e2e.test.ts +++ b/backend/test/ava-tests/saas-tests/company-info-e2e.test.ts @@ -7,12 +7,13 @@ import test from 'ava'; import { ValidationError } from 'class-validator'; import cookieParser from 'cookie-parser'; import fs from 'fs'; -import os from 'os'; import { nanoid } from 'nanoid'; +import os from 'os'; import path, { join } from 'path'; import request from 'supertest'; import { fileURLToPath } from 'url'; import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; import { Messages } from '../../../src/exceptions/text/messages.js'; @@ -22,12 +23,12 @@ import { DatabaseModule } from '../../../src/shared/database/database.module.js' import { DatabaseService } from '../../../src/shared/database/database.service.js'; import { MockFactory } from '../../mock.factory.js'; import { - inviteUserInCompanyAndAcceptInvitation, - inviteUserInCompanyAndGroupAndAcceptInvitation, + inviteUserInCompanyAndAcceptInvitation, + inviteUserInCompanyAndGroupAndAcceptInvitation, } from '../../utils/register-user-and-return-user-info.js'; import { TestUtils } from '../../utils/test.utils.js'; import { createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions } from '../../utils/user-with-different-permissions-utils.js'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; + const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -37,1538 +38,1540 @@ let _testUtils: TestUtils; let currentTest: string; test.before(async () => { - const moduleFixture = await Test.createTestingModule({ - imports: [ApplicationModule, DatabaseModule], - providers: [DatabaseService, TestUtils], - }).compile(); - app = moduleFixture.createNestApplication() as any; - _testUtils = moduleFixture.get(TestUtils); - - app.use(cookieParser()); - app.useGlobalFilters(new AllExceptionsFilter(app.get(WinstonLogger))); - app.useGlobalPipes( - new ValidationPipe({ - exceptionFactory(validationErrors: ValidationError[] = []) { - return new ValidationException(validationErrors); - }, - }), - ); - await app.init(); - app.getHttpServer().listen(0); + const moduleFixture = await Test.createTestingModule({ + imports: [ApplicationModule, DatabaseModule], + providers: [DatabaseService, TestUtils], + }).compile(); + app = moduleFixture.createNestApplication() as any; + _testUtils = moduleFixture.get(TestUtils); + + app.use(cookieParser()); + app.useGlobalFilters(new AllExceptionsFilter(app.get(WinstonLogger))); + app.useGlobalPipes( + new ValidationPipe({ + exceptionFactory(validationErrors: ValidationError[] = []) { + return new ValidationException(validationErrors); + }, + }), + ); + await app.init(); + app.getHttpServer().listen(0); }); test.after(async () => { - try { - await Cacher.clearAllCache(); - await app.close(); - } catch (e) { - console.error('After custom field error: ' + e); - } + try { + await Cacher.clearAllCache(); + await app.close(); + } catch (e) { + console.error('After custom field error: ' + e); + } }); currentTest = 'GET /company/my'; test.serial(`${currentTest} should return found company info for user`, async (t) => { - try { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my') - .set('Content-Type', 'application/json') - .set('Cookie', simpleUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - t.is(Object.keys(foundCompanyInfoRO).length, 10); - t.is(Object.hasOwn(foundCompanyInfoRO, 'id'), true); - t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); - t.is(Object.hasOwn(foundCompanyInfoRO, 'createdAt'), true); - t.is(Object.hasOwn(foundCompanyInfoRO, 'updatedAt'), true); - } catch (error) { - console.error(error); - } + try { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my') + .set('Content-Type', 'application/json') + .set('Cookie', simpleUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + t.is(Object.keys(foundCompanyInfoRO).length, 10); + t.is(Object.hasOwn(foundCompanyInfoRO, 'id'), true); + t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); + t.is(Object.hasOwn(foundCompanyInfoRO, 'createdAt'), true); + t.is(Object.hasOwn(foundCompanyInfoRO, 'updatedAt'), true); + } catch (error) { + console.error(error); + } }); currentTest = 'GET /company/my/full'; test.serial(`${currentTest} should return full found company info for company admin user`, async (t) => { - try { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - t.is(foundCompanyInfo.status, 200); - t.is(Object.hasOwn(foundCompanyInfoRO, 'id'), true); - t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); - t.is(Object.hasOwn(foundCompanyInfoRO, 'createdAt'), true); - t.is(Object.hasOwn(foundCompanyInfoRO, 'updatedAt'), true); - t.is(Object.keys(foundCompanyInfoRO).length, 15); - t.is(Object.hasOwn(foundCompanyInfoRO, 'connections'), true); - t.is(foundCompanyInfoRO.connections.length > 3, true); - t.is(Object.hasOwn(foundCompanyInfoRO, 'invitations'), true); - t.is(foundCompanyInfoRO.invitations.length, 0); - t.is(Object.keys(foundCompanyInfoRO.connections[0]).length, 7); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'id'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'title'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'createdAt'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'updatedAt'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'author'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'groups'), true); - t.is(foundCompanyInfoRO.connections[0].groups.length > 0, true); - t.is(Object.keys(foundCompanyInfoRO.connections[0].groups[0]).length, 4); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'id'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'title'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'isMain'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'users'), true); - t.is(foundCompanyInfoRO.connections[0].groups[0].users.length > 0, true); - t.is(Object.keys(foundCompanyInfoRO.connections[0].groups[0].users[0]).length, 9); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'id'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'email'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'role'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'createdAt'), true); - t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'password'), false); - } catch (error) { - console.error(error); - throw error; - } + try { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + t.is(foundCompanyInfo.status, 200); + t.is(Object.hasOwn(foundCompanyInfoRO, 'id'), true); + t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); + t.is(Object.hasOwn(foundCompanyInfoRO, 'createdAt'), true); + t.is(Object.hasOwn(foundCompanyInfoRO, 'updatedAt'), true); + t.is(Object.keys(foundCompanyInfoRO).length, 15); + t.is(Object.hasOwn(foundCompanyInfoRO, 'connections'), true); + t.is(foundCompanyInfoRO.connections.length > 3, true); + t.is(Object.hasOwn(foundCompanyInfoRO, 'invitations'), true); + t.is(foundCompanyInfoRO.invitations.length, 0); + t.is(Object.keys(foundCompanyInfoRO.connections[0]).length, 7); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'id'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'title'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'createdAt'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'updatedAt'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'author'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0], 'groups'), true); + t.is(foundCompanyInfoRO.connections[0].groups.length > 0, true); + t.is(Object.keys(foundCompanyInfoRO.connections[0].groups[0]).length, 4); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'id'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'title'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'isMain'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0], 'users'), true); + t.is(foundCompanyInfoRO.connections[0].groups[0].users.length > 0, true); + t.is(Object.keys(foundCompanyInfoRO.connections[0].groups[0].users[0]).length, 9); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'id'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'email'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'role'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'createdAt'), true); + t.is(Object.hasOwn(foundCompanyInfoRO.connections[0].groups[0].users[0], 'password'), false); + } catch (error) { + console.error(error); + throw error; + } }); test.serial(`${currentTest} should return found company info for non-admin user`, async (t) => { - try { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', simpleUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - t.is(foundCompanyInfo.status, 200); - t.is(Object.keys(foundCompanyInfoRO).length, 10); - t.is(Object.hasOwn(foundCompanyInfoRO, 'id'), true); - t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); - t.is(Object.hasOwn(foundCompanyInfoRO, 'createdAt'), true); - t.is(Object.hasOwn(foundCompanyInfoRO, 'updatedAt'), true); - } catch (error) { - console.error(error); - throw error; - } + try { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', simpleUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + t.is(foundCompanyInfo.status, 200); + t.is(Object.keys(foundCompanyInfoRO).length, 10); + t.is(Object.hasOwn(foundCompanyInfoRO, 'id'), true); + t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); + t.is(Object.hasOwn(foundCompanyInfoRO, 'createdAt'), true); + t.is(Object.hasOwn(foundCompanyInfoRO, 'updatedAt'), true); + } catch (error) { + console.error(error); + throw error; + } }); currentTest = 'GET /company/my/email'; test.serial(`${currentTest} should return found company infos for admin user`, async (t) => { - try { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get(`/company/my/email/${testData.users.adminUserEmail}`) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - t.is(foundCompanyInfo.status, 200); - t.is(Array.isArray(foundCompanyInfoRO), true); - t.is(foundCompanyInfoRO.length, 1); - t.is(Object.hasOwn(foundCompanyInfoRO[0], 'id'), true); - t.is(Object.keys(foundCompanyInfoRO[0]).length, 2); - t.is(Object.hasOwn(foundCompanyInfoRO[0], 'name'), true); - } catch (error) { - console.error(error); - throw error; - } + try { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get(`/company/my/email/${testData.users.adminUserEmail}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + t.is(foundCompanyInfo.status, 200); + t.is(Array.isArray(foundCompanyInfoRO), true); + t.is(foundCompanyInfoRO.length, 1); + t.is(Object.hasOwn(foundCompanyInfoRO[0], 'id'), true); + t.is(Object.keys(foundCompanyInfoRO[0]).length, 2); + t.is(Object.hasOwn(foundCompanyInfoRO[0], 'name'), true); + } catch (error) { + console.error(error); + throw error; + } }); test.serial(`${currentTest} should return found company infos for non-admin user`, async (t) => { - try { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get(`/company/my/email/${testData.users.simpleUserEmail}`) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - t.is(foundCompanyInfo.status, 200); - t.is(Array.isArray(foundCompanyInfoRO), true); - t.is(foundCompanyInfoRO.length, 1); - t.is(Object.keys(foundCompanyInfoRO[0]).length, 2); - t.is(Object.hasOwn(foundCompanyInfoRO[0], 'name'), true); - } catch (error) { - console.error(error); - throw error; - } + try { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get(`/company/my/email/${testData.users.simpleUserEmail}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + t.is(foundCompanyInfo.status, 200); + t.is(Array.isArray(foundCompanyInfoRO), true); + t.is(foundCompanyInfoRO.length, 1); + t.is(Object.keys(foundCompanyInfoRO[0]).length, 2); + t.is(Object.hasOwn(foundCompanyInfoRO[0], 'name'), true); + } catch (error) { + console.error(error); + throw error; + } }); currentTest = 'DELETE /:companyId/user/:userId'; test.serial(`${currentTest} should remove user from company`, async (t) => { - try { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - t.is(foundCompanyInfo.status, 200); - - const allGroupsInResult = foundCompanyInfoRO.connections.flatMap((connection) => connection.groups); - const allUsersInResult = allGroupsInResult.flatMap((group) => group.users); - const foundSimpleUserInResult = allUsersInResult.find((user) => user.email === simpleUserEmail.toLowerCase()); - - t.is(foundSimpleUserInResult.email, simpleUserEmail.toLowerCase()); - - const removeUserFromCompanyResult = await request(app.getHttpServer()) - .delete(`/company/${foundCompanyInfoRO.id}/user/${foundSimpleUserInResult.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const removeUserFromCompany = JSON.parse(removeUserFromCompanyResult.text); - - t.is(removeUserFromCompanyResult.status, 200); - t.is(removeUserFromCompany.success, true); - - const foundCompanyInfoAfterUserDeletion = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoROAfterUserDeletion = JSON.parse(foundCompanyInfoAfterUserDeletion.text); - - const allGroupsInResultAfterUserDeletion = foundCompanyInfoROAfterUserDeletion.connections - .flatMap((connection) => connection.groups); - const allUsersInResultAfterUserDeletion = allGroupsInResultAfterUserDeletion.flatMap((group) => group.users); - const foundSimpleUserInResultAfterUserDeletion = !!allUsersInResultAfterUserDeletion.find( - (user) => user.email === simpleUserEmail, - ); - - t.is(foundSimpleUserInResultAfterUserDeletion, false); - } catch (error) { - console.error(error); - throw error; - } + try { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + t.is(foundCompanyInfo.status, 200); + + const allGroupsInResult = foundCompanyInfoRO.connections.flatMap((connection) => connection.groups); + const allUsersInResult = allGroupsInResult.flatMap((group) => group.users); + const foundSimpleUserInResult = allUsersInResult.find((user) => user.email === simpleUserEmail.toLowerCase()); + + t.is(foundSimpleUserInResult.email, simpleUserEmail.toLowerCase()); + + const removeUserFromCompanyResult = await request(app.getHttpServer()) + .delete(`/company/${foundCompanyInfoRO.id}/user/${foundSimpleUserInResult.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const removeUserFromCompany = JSON.parse(removeUserFromCompanyResult.text); + + t.is(removeUserFromCompanyResult.status, 200); + t.is(removeUserFromCompany.success, true); + + const foundCompanyInfoAfterUserDeletion = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoROAfterUserDeletion = JSON.parse(foundCompanyInfoAfterUserDeletion.text); + + const allGroupsInResultAfterUserDeletion = foundCompanyInfoROAfterUserDeletion.connections.flatMap( + (connection) => connection.groups, + ); + const allUsersInResultAfterUserDeletion = allGroupsInResultAfterUserDeletion.flatMap((group) => group.users); + const foundSimpleUserInResultAfterUserDeletion = !!allUsersInResultAfterUserDeletion.find( + (user) => user.email === simpleUserEmail, + ); + + t.is(foundSimpleUserInResultAfterUserDeletion, false); + } catch (error) { + console.error(error); + throw error; + } }); test.serial( - `${currentTest} should remove user from company. User with the same email can be invited in this company one more time`, - async (t) => { - try { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, - groups: { createdGroupId }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - t.is(foundCompanyInfo.status, 200); - - const allGroupsInResult = foundCompanyInfoRO.connections.flatMap((connection) => connection.groups); - const allUsersInResult = allGroupsInResult.flatMap((group) => group.users); - const foundSimpleUserInResult = allUsersInResult.find((user) => user.email === simpleUserEmail.toLowerCase()); - - t.is(foundSimpleUserInResult.email, simpleUserEmail.toLowerCase()); - - const removeUserFromCompanyResult = await request(app.getHttpServer()) - .delete(`/company/${foundCompanyInfoRO.id}/user/${foundSimpleUserInResult.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const removeUserFromCompany = JSON.parse(removeUserFromCompanyResult.text); - - t.is(removeUserFromCompanyResult.status, 200); - t.is(removeUserFromCompany.success, true); - - const foundCompanyInfoAfterUserDeletion = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoROAfterUserDeletion = JSON.parse(foundCompanyInfoAfterUserDeletion.text); - - const allGroupsInResultAfterUserDeletion = foundCompanyInfoROAfterUserDeletion.connections - .flatMap((connection) => connection.groups); - const allUsersInResultAfterUserDeletion = allGroupsInResultAfterUserDeletion.flatMap((group) => group.users); - const foundSimpleUserInResultAfterUserDeletion = !!allUsersInResultAfterUserDeletion.find( - (user) => user.email === simpleUserEmail, - ); - - t.is(foundSimpleUserInResultAfterUserDeletion, false); - - const invitedDeletedUser = await inviteUserInCompanyAndAcceptInvitation( - adminUserToken, - 'USER', - app, - createdGroupId, - simpleUserEmail, - ); - t.is(invitedDeletedUser.email, simpleUserEmail); - t.truthy(invitedDeletedUser.token); - t.truthy(invitedDeletedUser.password); - } catch (error) { - console.error(error); - throw error; - } - }, + `${currentTest} should remove user from company. User with the same email can be invited in this company one more time`, + async (t) => { + try { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, + groups: { createdGroupId }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + t.is(foundCompanyInfo.status, 200); + + const allGroupsInResult = foundCompanyInfoRO.connections.flatMap((connection) => connection.groups); + const allUsersInResult = allGroupsInResult.flatMap((group) => group.users); + const foundSimpleUserInResult = allUsersInResult.find((user) => user.email === simpleUserEmail.toLowerCase()); + + t.is(foundSimpleUserInResult.email, simpleUserEmail.toLowerCase()); + + const removeUserFromCompanyResult = await request(app.getHttpServer()) + .delete(`/company/${foundCompanyInfoRO.id}/user/${foundSimpleUserInResult.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const removeUserFromCompany = JSON.parse(removeUserFromCompanyResult.text); + + t.is(removeUserFromCompanyResult.status, 200); + t.is(removeUserFromCompany.success, true); + + const foundCompanyInfoAfterUserDeletion = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoROAfterUserDeletion = JSON.parse(foundCompanyInfoAfterUserDeletion.text); + + const allGroupsInResultAfterUserDeletion = foundCompanyInfoROAfterUserDeletion.connections.flatMap( + (connection) => connection.groups, + ); + const allUsersInResultAfterUserDeletion = allGroupsInResultAfterUserDeletion.flatMap((group) => group.users); + const foundSimpleUserInResultAfterUserDeletion = !!allUsersInResultAfterUserDeletion.find( + (user) => user.email === simpleUserEmail, + ); + + t.is(foundSimpleUserInResultAfterUserDeletion, false); + + const invitedDeletedUser = await inviteUserInCompanyAndAcceptInvitation( + adminUserToken, + 'USER', + app, + createdGroupId, + simpleUserEmail, + ); + t.is(invitedDeletedUser.email, simpleUserEmail); + t.truthy(invitedDeletedUser.token); + t.truthy(invitedDeletedUser.password); + } catch (error) { + console.error(error); + throw error; + } + }, ); currentTest = 'PUT invitation/revoke/:slug'; test.serial(`${currentTest} should revoke user invitation from company`, async (t) => { - try { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - t.is(foundCompanyInfoRO.invitations.length, 0); - - const allGroupsInResult = foundCompanyInfoRO.connections.flatMap((connection) => connection.groups); - const allUsersInResult = allGroupsInResult.flatMap((group) => group.users); - const foundSimpleUserInResult = allUsersInResult.find((user) => user.email === simpleUserEmail.toLowerCase()); - - const removeUserFromCompanyResult = await request(app.getHttpServer()) - .delete(`/company/${foundCompanyInfoRO.id}/user/${foundSimpleUserInResult.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(removeUserFromCompanyResult.status, 200); - - const invitationRequestBody = { - companyId: foundCompanyInfoRO.id, - email: simpleUserEmail, - role: 'USER', - groupId: foundCompanyInfoRO.connections[0].groups[0].id, - }; - - const invitationResult = await request(app.getHttpServer()) - .put(`/company/user/${foundCompanyInfoRO.id}`) - .send(invitationRequestBody) - .set('Cookie', adminUserToken) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - t.is(invitationResult.status, 200); - - const foundCompanyInfoWithInvitation = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoWithInvitationRO = JSON.parse(foundCompanyInfoWithInvitation.text); - t.is(foundCompanyInfoWithInvitationRO.invitations.length, 1); - - const deleteInvitationResult = await request(app.getHttpServer()) - .put(`/company/invitation/revoke/${foundCompanyInfoRO.id}`) - .send({ - email: simpleUserEmail, - }) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(deleteInvitationResult.status, 200); - - const foundCompanyInfoAfterInvitationDeletion = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoROAfterInvitationDeletion = JSON.parse(foundCompanyInfoAfterInvitationDeletion.text); - t.is(foundCompanyInfoROAfterInvitationDeletion.invitations.length, 0); - } catch (error) { - console.error(error); - throw error; - } + try { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + t.is(foundCompanyInfoRO.invitations.length, 0); + + const allGroupsInResult = foundCompanyInfoRO.connections.flatMap((connection) => connection.groups); + const allUsersInResult = allGroupsInResult.flatMap((group) => group.users); + const foundSimpleUserInResult = allUsersInResult.find((user) => user.email === simpleUserEmail.toLowerCase()); + + const removeUserFromCompanyResult = await request(app.getHttpServer()) + .delete(`/company/${foundCompanyInfoRO.id}/user/${foundSimpleUserInResult.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(removeUserFromCompanyResult.status, 200); + + const invitationRequestBody = { + companyId: foundCompanyInfoRO.id, + email: simpleUserEmail, + role: 'USER', + groupId: foundCompanyInfoRO.connections[0].groups[0].id, + }; + + const invitationResult = await request(app.getHttpServer()) + .put(`/company/user/${foundCompanyInfoRO.id}`) + .send(invitationRequestBody) + .set('Cookie', adminUserToken) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + t.is(invitationResult.status, 200); + + const foundCompanyInfoWithInvitation = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoWithInvitationRO = JSON.parse(foundCompanyInfoWithInvitation.text); + t.is(foundCompanyInfoWithInvitationRO.invitations.length, 1); + + const deleteInvitationResult = await request(app.getHttpServer()) + .put(`/company/invitation/revoke/${foundCompanyInfoRO.id}`) + .send({ + email: simpleUserEmail, + }) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(deleteInvitationResult.status, 200); + + const foundCompanyInfoAfterInvitationDeletion = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoROAfterInvitationDeletion = JSON.parse(foundCompanyInfoAfterInvitationDeletion.text); + t.is(foundCompanyInfoROAfterInvitationDeletion.invitations.length, 0); + } catch (error) { + console.error(error); + throw error; + } }); currentTest = 'PUT company/name/:slug'; test.serial(`${currentTest} should update company name`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); - - const newName = `${faker.company.name()}_${nanoid(5)}`; - const updateCompanyNameResult = await request(app.getHttpServer()) - .put(`/company/name/${foundCompanyInfoRO.id}`) - .send({ - name: newName, - }) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - t.is(updateCompanyNameResult.status, 200); - - const foundCompanyInfoAfterUpdate = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - const foundCompanyInfoROAfterUpdate = JSON.parse(foundCompanyInfoAfterUpdate.text); - t.is(Object.hasOwn(foundCompanyInfoROAfterUpdate, 'name'), true); - t.is(foundCompanyInfoROAfterUpdate.name, newName); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + t.is(Object.hasOwn(foundCompanyInfoRO, 'name'), true); + + const newName = `${faker.company.name()}_${nanoid(5)}`; + const updateCompanyNameResult = await request(app.getHttpServer()) + .put(`/company/name/${foundCompanyInfoRO.id}`) + .send({ + name: newName, + }) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + t.is(updateCompanyNameResult.status, 200); + + const foundCompanyInfoAfterUpdate = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + const foundCompanyInfoROAfterUpdate = JSON.parse(foundCompanyInfoAfterUpdate.text); + t.is(Object.hasOwn(foundCompanyInfoROAfterUpdate, 'name'), true); + t.is(foundCompanyInfoROAfterUpdate.name, newName); }); currentTest = 'GET company/name/:companyId'; test.serial(`${currentTest} should return company name`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - const foundCompanyName = await request(app.getHttpServer()) - .get(`/company/name/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - t.is(foundCompanyName.status, 200); - const foundCompanyNameRO = JSON.parse(foundCompanyName.text); - t.is(Object.hasOwn(foundCompanyNameRO, 'name'), true); - t.is(foundCompanyNameRO.name, foundCompanyInfoRO.name); - t.pass(); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + const foundCompanyName = await request(app.getHttpServer()) + .get(`/company/name/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + t.is(foundCompanyName.status, 200); + const foundCompanyNameRO = JSON.parse(foundCompanyName.text); + t.is(Object.hasOwn(foundCompanyNameRO, 'name'), true); + t.is(foundCompanyNameRO.name, foundCompanyInfoRO.name); + t.pass(); }); currentTest = `GET company/users/:companyId`; test.serial(`${currentTest} should return users in company`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - const usersInCompany = await request(app.getHttpServer()) - .get(`/company/users/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(usersInCompany.status, 200); - const usersInCompanyRO = JSON.parse(usersInCompany.text); - t.is(usersInCompanyRO.length, 2); - - usersInCompanyRO.forEach((user) => { - t.true('id' in user); - t.true('isActive' in user); - t.true('email' in user); - t.true('createdAt' in user); - t.true('suspended' in user); - t.true('name' in user); - t.true('is_2fa_enabled' in user); - t.true('role' in user); - t.true('externalRegistrationProvider' in user); - t.true('user_membership' in user); - t.true('has_groups' in user); - - t.true(Array.isArray(user.user_membership)); - user.user_membership.forEach((user_membership) => { - t.true('id' in user_membership); - t.true('title' in user_membership); - t.true('database' in user_membership); - t.true(Array.isArray(user_membership.groups)); - user_membership.groups.forEach((group) => { - t.true('id' in group); - t.true('title' in group); - t.is(Object.keys(group).length, 2); - }); - }); - }); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + const usersInCompany = await request(app.getHttpServer()) + .get(`/company/users/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(usersInCompany.status, 200); + const usersInCompanyRO = JSON.parse(usersInCompany.text); + t.is(usersInCompanyRO.length, 2); + + usersInCompanyRO.forEach((user) => { + t.true('id' in user); + t.true('isActive' in user); + t.true('email' in user); + t.true('createdAt' in user); + t.true('suspended' in user); + t.true('name' in user); + t.true('is_2fa_enabled' in user); + t.true('role' in user); + t.true('externalRegistrationProvider' in user); + t.true('user_membership' in user); + t.true('has_groups' in user); + + t.true(Array.isArray(user.user_membership)); + user.user_membership.forEach((user_membership) => { + t.true('id' in user_membership); + t.true('title' in user_membership); + t.true('database' in user_membership); + t.true(Array.isArray(user_membership.groups)); + user_membership.groups.forEach((group) => { + t.true('id' in group); + t.true('title' in group); + t.is(Object.keys(group).length, 2); + }); + }); + }); }); currentTest = `PUT company/users/roles/:companyId`; test.serial(`${currentTest} should update user roles in company`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - const usersInCompany = await request(app.getHttpServer()) - .get(`/company/users/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(usersInCompany.status, 200); - const usersInCompanyRO = JSON.parse(usersInCompany.text); - - t.is(usersInCompanyRO.length, 2); - - const foundNonAdminUser = usersInCompanyRO.find((user) => user.role === 'USER'); - t.is(!!foundNonAdminUser, true); - - const updateUserRoleRequest = { - users: [ - { - userId: foundNonAdminUser.id, - role: 'ADMIN', - }, - ], - }; - - const updateUserRoleResult = await request(app.getHttpServer()) - .put(`/company/users/roles/${foundCompanyInfoRO.id}`) - .send(updateUserRoleRequest) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(updateUserRoleResult.status, 200); - const updateUserRoleResultRO = JSON.parse(updateUserRoleResult.text); - t.is(updateUserRoleResultRO.success, true); - - const usersInCompanyAfterUpdate = await request(app.getHttpServer()) - .get(`/company/users/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(usersInCompanyAfterUpdate.status, 200); - const usersInCompanyROAfterUpdate = JSON.parse(usersInCompanyAfterUpdate.text); - - t.is(usersInCompanyROAfterUpdate.length, 2); - - for (const user of usersInCompanyROAfterUpdate) { - t.is(user.role, 'ADMIN'); - } + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + const usersInCompany = await request(app.getHttpServer()) + .get(`/company/users/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(usersInCompany.status, 200); + const usersInCompanyRO = JSON.parse(usersInCompany.text); + + t.is(usersInCompanyRO.length, 2); + + const foundNonAdminUser = usersInCompanyRO.find((user) => user.role === 'USER'); + t.is(!!foundNonAdminUser, true); + + const updateUserRoleRequest = { + users: [ + { + userId: foundNonAdminUser.id, + role: 'ADMIN', + }, + ], + }; + + const updateUserRoleResult = await request(app.getHttpServer()) + .put(`/company/users/roles/${foundCompanyInfoRO.id}`) + .send(updateUserRoleRequest) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(updateUserRoleResult.status, 200); + const updateUserRoleResultRO = JSON.parse(updateUserRoleResult.text); + t.is(updateUserRoleResultRO.success, true); + + const usersInCompanyAfterUpdate = await request(app.getHttpServer()) + .get(`/company/users/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(usersInCompanyAfterUpdate.status, 200); + const usersInCompanyROAfterUpdate = JSON.parse(usersInCompanyAfterUpdate.text); + + t.is(usersInCompanyROAfterUpdate.length, 2); + + for (const user of usersInCompanyROAfterUpdate) { + t.is(user.role, 'ADMIN'); + } }); currentTest = `DELETE company`; test.serial(`${currentTest} should delete company`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, - } = testData; - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - - const deleteCompanyResult = await request(app.getHttpServer()) - .delete(`/company/my`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const deleteCompanyResultRO = JSON.parse(deleteCompanyResult.text); - t.is(deleteCompanyResult.status, 200); - t.is(deleteCompanyResultRO.success, true); - - const foundCompanyInfoAfterDelete = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfoAfterDelete.status, 401); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail }, + } = testData; + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + + const deleteCompanyResult = await request(app.getHttpServer()) + .delete(`/company/my`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const deleteCompanyResultRO = JSON.parse(deleteCompanyResult.text); + t.is(deleteCompanyResult.status, 200); + t.is(deleteCompanyResultRO.success, true); + + const foundCompanyInfoAfterDelete = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfoAfterDelete.status, 401); }); currentTest = `PUT company/2fa/:companyId`; test.serial(`${currentTest} should enable 2fa for company`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - - const foundCompanyRo = JSON.parse(foundCompanyInfo.text); - t.is(Object.hasOwn(foundCompanyRo, 'is2faEnabled'), true); - t.is(foundCompanyRo.is2faEnabled, false); - - const requestBody = { - is2faEnabled: true, - }; - const enable2faResult = await request(app.getHttpServer()) - .put(`/company/2fa/${foundCompanyRo.id}`) - .send(requestBody) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(enable2faResult.status, 200); - - const foundCompanyInfoAfterUpdate = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfoAfterUpdate.status, 200); - const foundCompanyRoAfterUpdate = JSON.parse(foundCompanyInfoAfterUpdate.text); - t.is(Object.hasOwn(foundCompanyRoAfterUpdate, 'is2faEnabled'), true); - t.is(foundCompanyRoAfterUpdate.is2faEnabled, true); - - // user should not be able to use endpoints that require 2fa after login - - const userLoginInfo = { - email: simpleUserEmail, - password: simpleUserPassword, - }; - - const loginUserResponse = await request(app.getHttpServer()) - .post('/user/login/') - .send(userLoginInfo) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - if (loginUserResponse.status > 201) { - console.info('loginUserResponse.text -> ', loginUserResponse.text); - } - - const newSimpleUserToken = `${Constants.JWT_COOKIE_KEY_NAME}=${TestUtils.getJwtTokenFromResponse(loginUserResponse)}`; - const connectionsResult = await request(app.getHttpServer()) - .get('/connections') - .set('Content-Type', 'application/json') - .set('Cookie', newSimpleUserToken) - .set('Accept', 'application/json'); - - t.is(connectionsResult.status, 400); - - const connectionsResultsObject = JSON.parse(connectionsResult.text); - t.is(connectionsResultsObject.message, Messages.TWO_FA_REQUIRED); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + + const foundCompanyRo = JSON.parse(foundCompanyInfo.text); + t.is(Object.hasOwn(foundCompanyRo, 'is2faEnabled'), true); + t.is(foundCompanyRo.is2faEnabled, false); + + const requestBody = { + is2faEnabled: true, + }; + const enable2faResult = await request(app.getHttpServer()) + .put(`/company/2fa/${foundCompanyRo.id}`) + .send(requestBody) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(enable2faResult.status, 200); + + const foundCompanyInfoAfterUpdate = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfoAfterUpdate.status, 200); + const foundCompanyRoAfterUpdate = JSON.parse(foundCompanyInfoAfterUpdate.text); + t.is(Object.hasOwn(foundCompanyRoAfterUpdate, 'is2faEnabled'), true); + t.is(foundCompanyRoAfterUpdate.is2faEnabled, true); + + // user should not be able to use endpoints that require 2fa after login + + const userLoginInfo = { + email: simpleUserEmail, + password: simpleUserPassword, + }; + + const loginUserResponse = await request(app.getHttpServer()) + .post('/user/login/') + .send(userLoginInfo) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + if (loginUserResponse.status > 201) { + console.info('loginUserResponse.text -> ', loginUserResponse.text); + } + + const newSimpleUserToken = `${Constants.JWT_COOKIE_KEY_NAME}=${TestUtils.getJwtTokenFromResponse(loginUserResponse)}`; + const connectionsResult = await request(app.getHttpServer()) + .get('/connections') + .set('Content-Type', 'application/json') + .set('Cookie', newSimpleUserToken) + .set('Accept', 'application/json'); + + t.is(connectionsResult.status, 400); + + const connectionsResultsObject = JSON.parse(connectionsResult.text); + t.is(connectionsResultsObject.message, Messages.TWO_FA_REQUIRED); }); currentTest = `PUT /subscription/upgrade/:companyId`; test.serial( - `${currentTest} should call function subscription upgrade for company in sass, and suspend users`, - async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - let firstConnection = foundCompanyInfoRO.connections.find( - (connectionRO) => connections.firstId === connectionRO.id, - ); - const createdGroup = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); - - const additionalUsers: Array<{ - email: string; - password: string; - token: string; - }> = []; - for (let i = 0; i < 5; i++) { - const invitationResult = await inviteUserInCompanyAndGroupAndAcceptInvitation( - adminUserToken, - 'USER', - createdGroup.id, - app, - ); - additionalUsers.push(invitationResult); - } - const foundCompanyInfoWithAddedUsers = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - const foundCompanyInfoWithAddedUsersRO = JSON.parse(foundCompanyInfoWithAddedUsers.text); - firstConnection = foundCompanyInfoWithAddedUsersRO.connections.find( - (connectionRO) => connections.firstId === connectionRO.id, - ); - const { users } = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); - users.forEach((user: any) => { - t.is(user.suspended, false); - }); - - const _subscriptionUpgradeResult = await fetch( - `http://rocketadmin-private-microservice:3001/saas/company/subscription/upgrade/${foundCompanyInfoRO.id}`, - { - method: 'POST', - headers: { - Cookie: adminUserToken, - 'Content-Type': 'application/json', - Accept: 'application/json', - }, - body: JSON.stringify({ - subscriptionLevel: 'FREE_PLAN', - }), - }, - ); - - const foundCompanyInfoAfterUpgrade = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoAfterUpgradeRO = JSON.parse(foundCompanyInfoAfterUpgrade.text); - - firstConnection = foundCompanyInfoAfterUpgradeRO.connections.find( - (connectionRO) => connections.firstId === connectionRO.id, - ); - const { users: usersAfterUpgrade } = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); - const suspendUsersCount = usersAfterUpgrade.filter((user: any) => user.suspended).length; - t.is(suspendUsersCount, 4); - const unSuspendedUsersCount = usersAfterUpgrade.filter((user: any) => !user.suspended).length; - t.is(unSuspendedUsersCount, 3); - - // suspended users should not be able to access endpoints - - const findAllConnectionsResponse = await request(app.getHttpServer()) - .get('/connections') - .set('Cookie', additionalUsers[additionalUsers.length - 1].token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const findAllConnectionsResponseRO = JSON.parse(findAllConnectionsResponse.text); - t.is(findAllConnectionsResponse.status, 401); - t.is(findAllConnectionsResponseRO.message, Messages.ACCOUNT_SUSPENDED); - }, + `${currentTest} should call function subscription upgrade for company in sass, and suspend users`, + async (t) => { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + let firstConnection = foundCompanyInfoRO.connections.find( + (connectionRO) => connections.firstId === connectionRO.id, + ); + const createdGroup = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); + + const additionalUsers: Array<{ + email: string; + password: string; + token: string; + }> = []; + for (let i = 0; i < 5; i++) { + const invitationResult = await inviteUserInCompanyAndGroupAndAcceptInvitation( + adminUserToken, + 'USER', + createdGroup.id, + app, + ); + additionalUsers.push(invitationResult); + } + const foundCompanyInfoWithAddedUsers = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + const foundCompanyInfoWithAddedUsersRO = JSON.parse(foundCompanyInfoWithAddedUsers.text); + firstConnection = foundCompanyInfoWithAddedUsersRO.connections.find( + (connectionRO) => connections.firstId === connectionRO.id, + ); + const { users } = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); + users.forEach((user: any) => { + t.is(user.suspended, false); + }); + + const _subscriptionUpgradeResult = await fetch( + `http://rocketadmin-private-microservice:3001/saas/company/subscription/upgrade/${foundCompanyInfoRO.id}`, + { + method: 'POST', + headers: { + Cookie: adminUserToken, + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + body: JSON.stringify({ + subscriptionLevel: 'FREE_PLAN', + }), + }, + ); + + const foundCompanyInfoAfterUpgrade = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoAfterUpgradeRO = JSON.parse(foundCompanyInfoAfterUpgrade.text); + + firstConnection = foundCompanyInfoAfterUpgradeRO.connections.find( + (connectionRO) => connections.firstId === connectionRO.id, + ); + const { users: usersAfterUpgrade } = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); + const suspendUsersCount = usersAfterUpgrade.filter((user: any) => user.suspended).length; + t.is(suspendUsersCount, 4); + const unSuspendedUsersCount = usersAfterUpgrade.filter((user: any) => !user.suspended).length; + t.is(unSuspendedUsersCount, 3); + + // suspended users should not be able to access endpoints + + const findAllConnectionsResponse = await request(app.getHttpServer()) + .get('/connections') + .set('Cookie', additionalUsers[additionalUsers.length - 1].token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const findAllConnectionsResponseRO = JSON.parse(findAllConnectionsResponse.text); + t.is(findAllConnectionsResponse.status, 401); + t.is(findAllConnectionsResponseRO.message, Messages.ACCOUNT_SUSPENDED); + }, ); currentTest = `PUT /company/users/suspend/:companyId`; test.serial(`${currentTest} should suspend users in company`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - let firstConnection = foundCompanyInfoRO.connections.find((connectionRO) => connections.firstId === connectionRO.id); - const createdGroup = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); - - const additionalUsers: Array<{ - email: string; - password: string; - token: string; - }> = []; - for (let i = 0; i < 5; i++) { - const invitationResult = await inviteUserInCompanyAndGroupAndAcceptInvitation( - adminUserToken, - 'USER', - createdGroup.id, - app, - ); - additionalUsers.push(invitationResult); - } - const foundCompanyInfoWithAddedUsers = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - const foundCompanyInfoWithAddedUsersRO = JSON.parse(foundCompanyInfoWithAddedUsers.text); - firstConnection = foundCompanyInfoWithAddedUsersRO.connections.find( - (connectionRO) => connections.firstId === connectionRO.id, - ); - const { users } = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); - users.forEach((user: any) => { - t.is(user.suspended, false); - }); - - const suspendUsersResult = await request(app.getHttpServer()) - .put(`/company/users/suspend/${foundCompanyInfoRO.id}`) - .send({ - usersEmails: additionalUsers.map((user: any) => user.email), - }) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(suspendUsersResult.status, 200); - - const foundCompanyInfoAfterSuspend = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoAfterSuspendRO = JSON.parse(foundCompanyInfoAfterSuspend.text); - firstConnection = foundCompanyInfoAfterSuspendRO.connections.find( - (connectionRO) => connections.firstId === connectionRO.id, - ); - const { users: usersAfterSuspend } = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); - const suspendUsersCount = usersAfterSuspend.filter((user: any) => user.suspended).length; - t.is(suspendUsersCount, 5); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + let firstConnection = foundCompanyInfoRO.connections.find((connectionRO) => connections.firstId === connectionRO.id); + const createdGroup = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); + + const additionalUsers: Array<{ + email: string; + password: string; + token: string; + }> = []; + for (let i = 0; i < 5; i++) { + const invitationResult = await inviteUserInCompanyAndGroupAndAcceptInvitation( + adminUserToken, + 'USER', + createdGroup.id, + app, + ); + additionalUsers.push(invitationResult); + } + const foundCompanyInfoWithAddedUsers = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + const foundCompanyInfoWithAddedUsersRO = JSON.parse(foundCompanyInfoWithAddedUsers.text); + firstConnection = foundCompanyInfoWithAddedUsersRO.connections.find( + (connectionRO) => connections.firstId === connectionRO.id, + ); + const { users } = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); + users.forEach((user: any) => { + t.is(user.suspended, false); + }); + + const suspendUsersResult = await request(app.getHttpServer()) + .put(`/company/users/suspend/${foundCompanyInfoRO.id}`) + .send({ + usersEmails: additionalUsers.map((user: any) => user.email), + }) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(suspendUsersResult.status, 200); + + const foundCompanyInfoAfterSuspend = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoAfterSuspendRO = JSON.parse(foundCompanyInfoAfterSuspend.text); + firstConnection = foundCompanyInfoAfterSuspendRO.connections.find( + (connectionRO) => connections.firstId === connectionRO.id, + ); + const { users: usersAfterSuspend } = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); + const suspendUsersCount = usersAfterSuspend.filter((user: any) => user.suspended).length; + t.is(suspendUsersCount, 5); }); currentTest = `PUT /company/users/unsuspend/:companyId`; test.serial(`${currentTest} should suspend users in company`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - let firstConnection = foundCompanyInfoRO.connections.find((connectionRO) => connections.firstId === connectionRO.id); - const createdGroup = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); - - const additionalUsers: Array<{ - email: string; - password: string; - token: string; - }> = []; - for (let i = 0; i < 5; i++) { - const invitationResult = await inviteUserInCompanyAndGroupAndAcceptInvitation( - adminUserToken, - 'USER', - createdGroup.id, - app, - ); - additionalUsers.push(invitationResult); - } - const foundCompanyInfoWithAddedUsers = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - const foundCompanyInfoWithAddedUsersRO = JSON.parse(foundCompanyInfoWithAddedUsers.text); - firstConnection = foundCompanyInfoWithAddedUsersRO.connections.find( - (connectionRO) => connections.firstId === connectionRO.id, - ); - const { users } = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); - users.forEach((user: any) => { - t.is(user.suspended, false); - }); - - const suspendUsersResult = await request(app.getHttpServer()) - .put(`/company/users/suspend/${foundCompanyInfoRO.id}`) - .send({ - usersEmails: additionalUsers.map((user: any) => user.email), - }) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(suspendUsersResult.status, 200); - - const foundCompanyInfoAfterSuspend = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoAfterSuspendRO = JSON.parse(foundCompanyInfoAfterSuspend.text); - firstConnection = foundCompanyInfoAfterSuspendRO.connections.find( - (connectionRO) => connections.firstId === connectionRO.id, - ); - const { users: usersAfterSuspend } = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); - const suspendUsersCount = usersAfterSuspend.filter((user: any) => user.suspended).length; - t.is(suspendUsersCount, 5); - - const unsuspendUsersResult = await request(app.getHttpServer()) - .put(`/company/users/unsuspend/${foundCompanyInfoRO.id}`) - .send({ - usersEmails: additionalUsers.map((user: any) => user.email), - }) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(unsuspendUsersResult.status, 200); - - const foundCompanyInfoAfterUnsuspend = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - const foundCompanyInfoAfterUnsuspendRO = JSON.parse(foundCompanyInfoAfterUnsuspend.text); - firstConnection = foundCompanyInfoAfterUnsuspendRO.connections.find( - (connectionRO) => connections.firstId === connectionRO.id, - ); - const { users: usersAfterUnsuspend } = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); - const unsuspendUsersCount = usersAfterUnsuspend.filter((user: any) => !user.suspended).length; - t.is(unsuspendUsersCount, 7); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + let firstConnection = foundCompanyInfoRO.connections.find((connectionRO) => connections.firstId === connectionRO.id); + const createdGroup = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); + + const additionalUsers: Array<{ + email: string; + password: string; + token: string; + }> = []; + for (let i = 0; i < 5; i++) { + const invitationResult = await inviteUserInCompanyAndGroupAndAcceptInvitation( + adminUserToken, + 'USER', + createdGroup.id, + app, + ); + additionalUsers.push(invitationResult); + } + const foundCompanyInfoWithAddedUsers = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + const foundCompanyInfoWithAddedUsersRO = JSON.parse(foundCompanyInfoWithAddedUsers.text); + firstConnection = foundCompanyInfoWithAddedUsersRO.connections.find( + (connectionRO) => connections.firstId === connectionRO.id, + ); + const { users } = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); + users.forEach((user: any) => { + t.is(user.suspended, false); + }); + + const suspendUsersResult = await request(app.getHttpServer()) + .put(`/company/users/suspend/${foundCompanyInfoRO.id}`) + .send({ + usersEmails: additionalUsers.map((user: any) => user.email), + }) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(suspendUsersResult.status, 200); + + const foundCompanyInfoAfterSuspend = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoAfterSuspendRO = JSON.parse(foundCompanyInfoAfterSuspend.text); + firstConnection = foundCompanyInfoAfterSuspendRO.connections.find( + (connectionRO) => connections.firstId === connectionRO.id, + ); + const { users: usersAfterSuspend } = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); + const suspendUsersCount = usersAfterSuspend.filter((user: any) => user.suspended).length; + t.is(suspendUsersCount, 5); + + const unsuspendUsersResult = await request(app.getHttpServer()) + .put(`/company/users/unsuspend/${foundCompanyInfoRO.id}`) + .send({ + usersEmails: additionalUsers.map((user: any) => user.email), + }) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(unsuspendUsersResult.status, 200); + + const foundCompanyInfoAfterUnsuspend = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + const foundCompanyInfoAfterUnsuspendRO = JSON.parse(foundCompanyInfoAfterUnsuspend.text); + firstConnection = foundCompanyInfoAfterUnsuspendRO.connections.find( + (connectionRO) => connections.firstId === connectionRO.id, + ); + const { users: usersAfterUnsuspend } = firstConnection.groups.find((groupRO) => groupRO.id === groups.createdGroupId); + const unsuspendUsersCount = usersAfterUnsuspend.filter((user: any) => !user.suspended).length; + t.is(unsuspendUsersCount, 7); }); currentTest = 'PUT /company/connections/display/'; test.serial( - `${currentTest} should toggle to 'off ' show test connections option in company. Test connections should not be returned `, - async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - const _foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - const foundUserTestConnectionsInfo = await request(app.getHttpServer()) - .get('/connections') - .set('Cookie', simpleUserToken) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - t.is(foundUserTestConnectionsInfo.status, 200); - - const result = foundUserTestConnectionsInfo.body.connections; - - t.is(result.length, 5); - - // toggle to off - const toggleTestConnectionsResponse = await request(app.getHttpServer()) - .put('/company/connections/display/?displayMode=off') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - t.is(toggleTestConnectionsResponse.status, 200); - - const resultAfterToggle = await request(app.getHttpServer()) - .get('/connections') - .set('Cookie', simpleUserToken) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const resultAfterToggleRO = JSON.parse(resultAfterToggle.text); - t.is(resultAfterToggle.status, 200); - t.is(resultAfterToggleRO.connections.length, 1); - - // toggle to on - - const toggleTestConnectionsResponseOn = await request(app.getHttpServer()) - .put('/company/connections/display/?displayMode=on') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(toggleTestConnectionsResponseOn.status, 200); - - const resultAfterToggleOn = await request(app.getHttpServer()) - .get('/connections') - .set('Cookie', simpleUserToken) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const resultAfterToggleOnRO = JSON.parse(resultAfterToggleOn.text); - - t.is(resultAfterToggleOn.status, 200); - t.is(resultAfterToggleOnRO.connections.length, 5); - }, + `${currentTest} should toggle to 'off ' show test connections option in company. Test connections should not be returned `, + async (t) => { + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + const _foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + const foundUserTestConnectionsInfo = await request(app.getHttpServer()) + .get('/connections') + .set('Cookie', simpleUserToken) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + t.is(foundUserTestConnectionsInfo.status, 200); + + const result = foundUserTestConnectionsInfo.body.connections; + + t.is(result.length, 5); + + // toggle to off + const toggleTestConnectionsResponse = await request(app.getHttpServer()) + .put('/company/connections/display/?displayMode=off') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + t.is(toggleTestConnectionsResponse.status, 200); + + const resultAfterToggle = await request(app.getHttpServer()) + .get('/connections') + .set('Cookie', simpleUserToken) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const resultAfterToggleRO = JSON.parse(resultAfterToggle.text); + t.is(resultAfterToggle.status, 200); + t.is(resultAfterToggleRO.connections.length, 1); + + // toggle to on + + const toggleTestConnectionsResponseOn = await request(app.getHttpServer()) + .put('/company/connections/display/?displayMode=on') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(toggleTestConnectionsResponseOn.status, 200); + + const resultAfterToggleOn = await request(app.getHttpServer()) + .get('/connections') + .set('Cookie', simpleUserToken) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const resultAfterToggleOnRO = JSON.parse(resultAfterToggleOn.text); + + t.is(resultAfterToggleOn.status, 200); + t.is(resultAfterToggleOnRO.connections.length, 5); + }, ); currentTest = 'POST & GET /company/logo/:companyId'; test.serial(`${currentTest} should create and return found company logo after creation`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - const testLogoPatch = join(process.cwd(), 'test', 'ava-tests', 'test-files', 'test_logo.png'); - const downloadedLogoPatch = join(os.tmpdir(), `${foundCompanyInfoRO.id}_test_logo.png`); - - const createLogoResponse = await request(app.getHttpServer()) - .post(`/company/logo/${foundCompanyInfoRO.id}`) - .attach('file', testLogoPatch) - .set('Content-Type', 'image/png') - .set('Cookie', adminUserToken) - .set('Accept', 'image/png'); - - const _createLogoRO = JSON.parse(createLogoResponse.text); - t.is(createLogoResponse.status, 201); - - const foundCompanyLogo = await request(app.getHttpServer()) - .get(`/company/logo/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyLogo.status, 200); - const foundCompanyLogoRO = JSON.parse(foundCompanyLogo.text); - t.is(foundCompanyLogoRO.logo.mimeType, 'image/png'); - t.is(foundCompanyLogoRO.logo.image.length > 0, true); - fs.writeFileSync(downloadedLogoPatch, foundCompanyLogoRO.logo.image); - const isFileExists = fs.existsSync(downloadedLogoPatch); - - t.is(isFileExists, true); - - // should return company logo for simple user - - const foundCompanyLogoForSimpleUser = await request(app.getHttpServer()) - .get(`/company/logo/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', simpleUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyLogoForSimpleUser.status, 200); - const foundCompanyLogoForSimpleUserRO = JSON.parse(foundCompanyLogoForSimpleUser.text); - t.is(foundCompanyLogoForSimpleUserRO.logo.mimeType, 'image/png'); - t.is(foundCompanyLogoForSimpleUserRO.logo.image.length > 0, true); - - const downloadedLogoPatchForSimpleUser = join(os.tmpdir(), `${foundCompanyInfoRO.id}_simple_user_logo.png`); - - fs.writeFileSync(downloadedLogoPatchForSimpleUser, foundCompanyLogoForSimpleUserRO.logo.image); - const isFileExistsForSimpleUser = fs.existsSync(downloadedLogoPatchForSimpleUser); - t.is(isFileExistsForSimpleUser, true); - - //should return logo in full company info for admin - const foundCompanyInfoWithLogo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfoWithLogo.status, 200); - const foundCompanyInfoWithLogoRO = JSON.parse(foundCompanyInfoWithLogo.text); - t.is(Object.hasOwn(foundCompanyInfoWithLogoRO, 'logo'), true); - t.is(foundCompanyInfoWithLogoRO.logo.mimeType, 'image/png'); - t.is(foundCompanyInfoWithLogoRO.logo.image.length > 0, true); - - const downloadedLogoPatchWithLogo = join(os.tmpdir(), `${foundCompanyInfoWithLogoRO.id}_admin_user_logo.png`); - - fs.writeFileSync(downloadedLogoPatchWithLogo, foundCompanyInfoWithLogoRO.logo.image); - const isFileExistsWithLogo = fs.existsSync(downloadedLogoPatchWithLogo); - t.is(isFileExistsWithLogo, true); - - //should return logo in full company info for simple user - const foundCompanyInfoWithLogoForSimpleUser = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', simpleUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfoWithLogoForSimpleUser.status, 200); - const foundCompanyInfoWithLogoForSimpleUserRO = JSON.parse(foundCompanyInfoWithLogoForSimpleUser.text); - t.is(Object.hasOwn(foundCompanyInfoWithLogoForSimpleUserRO, 'logo'), true); - t.is(foundCompanyInfoWithLogoForSimpleUserRO.logo.mimeType, 'image/png'); - t.is(foundCompanyInfoWithLogoForSimpleUserRO.logo.image.length > 0, true); - - const downloadedLogoPatchForSimpleUserWithLogo = join( - os.tmpdir(), - `${foundCompanyInfoWithLogoForSimpleUserRO.id}_simple_user_logo.png`, - ); - - fs.writeFileSync(downloadedLogoPatchForSimpleUserWithLogo, foundCompanyInfoWithLogoForSimpleUserRO.logo.image); - const isFileExistsForSimpleUserWithLogo = fs.existsSync(downloadedLogoPatchForSimpleUserWithLogo); - t.is(isFileExistsForSimpleUserWithLogo, true); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + const testLogoPatch = join(process.cwd(), 'test', 'ava-tests', 'test-files', 'test_logo.png'); + const downloadedLogoPatch = join(os.tmpdir(), `${foundCompanyInfoRO.id}_test_logo.png`); + + const createLogoResponse = await request(app.getHttpServer()) + .post(`/company/logo/${foundCompanyInfoRO.id}`) + .attach('file', testLogoPatch) + .set('Content-Type', 'image/png') + .set('Cookie', adminUserToken) + .set('Accept', 'image/png'); + + const _createLogoRO = JSON.parse(createLogoResponse.text); + t.is(createLogoResponse.status, 201); + + const foundCompanyLogo = await request(app.getHttpServer()) + .get(`/company/logo/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyLogo.status, 200); + const foundCompanyLogoRO = JSON.parse(foundCompanyLogo.text); + t.is(foundCompanyLogoRO.logo.mimeType, 'image/png'); + t.is(foundCompanyLogoRO.logo.image.length > 0, true); + fs.writeFileSync(downloadedLogoPatch, foundCompanyLogoRO.logo.image); + const isFileExists = fs.existsSync(downloadedLogoPatch); + + t.is(isFileExists, true); + + // should return company logo for simple user + + const foundCompanyLogoForSimpleUser = await request(app.getHttpServer()) + .get(`/company/logo/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', simpleUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyLogoForSimpleUser.status, 200); + const foundCompanyLogoForSimpleUserRO = JSON.parse(foundCompanyLogoForSimpleUser.text); + t.is(foundCompanyLogoForSimpleUserRO.logo.mimeType, 'image/png'); + t.is(foundCompanyLogoForSimpleUserRO.logo.image.length > 0, true); + + const downloadedLogoPatchForSimpleUser = join(os.tmpdir(), `${foundCompanyInfoRO.id}_simple_user_logo.png`); + + fs.writeFileSync(downloadedLogoPatchForSimpleUser, foundCompanyLogoForSimpleUserRO.logo.image); + const isFileExistsForSimpleUser = fs.existsSync(downloadedLogoPatchForSimpleUser); + t.is(isFileExistsForSimpleUser, true); + + //should return logo in full company info for admin + const foundCompanyInfoWithLogo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfoWithLogo.status, 200); + const foundCompanyInfoWithLogoRO = JSON.parse(foundCompanyInfoWithLogo.text); + t.is(Object.hasOwn(foundCompanyInfoWithLogoRO, 'logo'), true); + t.is(foundCompanyInfoWithLogoRO.logo.mimeType, 'image/png'); + t.is(foundCompanyInfoWithLogoRO.logo.image.length > 0, true); + + const downloadedLogoPatchWithLogo = join(os.tmpdir(), `${foundCompanyInfoWithLogoRO.id}_admin_user_logo.png`); + + fs.writeFileSync(downloadedLogoPatchWithLogo, foundCompanyInfoWithLogoRO.logo.image); + const isFileExistsWithLogo = fs.existsSync(downloadedLogoPatchWithLogo); + t.is(isFileExistsWithLogo, true); + + //should return logo in full company info for simple user + const foundCompanyInfoWithLogoForSimpleUser = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', simpleUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfoWithLogoForSimpleUser.status, 200); + const foundCompanyInfoWithLogoForSimpleUserRO = JSON.parse(foundCompanyInfoWithLogoForSimpleUser.text); + t.is(Object.hasOwn(foundCompanyInfoWithLogoForSimpleUserRO, 'logo'), true); + t.is(foundCompanyInfoWithLogoForSimpleUserRO.logo.mimeType, 'image/png'); + t.is(foundCompanyInfoWithLogoForSimpleUserRO.logo.image.length > 0, true); + + const downloadedLogoPatchForSimpleUserWithLogo = join( + os.tmpdir(), + `${foundCompanyInfoWithLogoForSimpleUserRO.id}_simple_user_logo.png`, + ); + + fs.writeFileSync(downloadedLogoPatchForSimpleUserWithLogo, foundCompanyInfoWithLogoForSimpleUserRO.logo.image); + const isFileExistsForSimpleUserWithLogo = fs.existsSync(downloadedLogoPatchForSimpleUserWithLogo); + t.is(isFileExistsForSimpleUserWithLogo, true); }); currentTest = 'POST & GET /company/favicon/:companyId'; test.serial(`${currentTest} should create and return found company favicon after creation`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - const testFaviconPatch = join(process.cwd(), 'test', 'ava-tests', 'test-files', 'test_logo.png'); - const downloadedFaviconPatch = join(os.tmpdir(), `${foundCompanyInfoRO.id}_test_favicon.png`); - - const createFaviconResponse = await request(app.getHttpServer()) - .post(`/company/favicon/${foundCompanyInfoRO.id}`) - .attach('file', testFaviconPatch) - .set('Content-Type', 'image/png') - .set('Cookie', adminUserToken) - .set('Accept', 'image/png'); - - const _createFaviconRO = JSON.parse(createFaviconResponse.text); - t.is(createFaviconResponse.status, 201); - - const foundCompanyFavicon = await request(app.getHttpServer()) - .get(`/company/favicon/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyFavicon.status, 200); - const foundCompanyFaviconRO = JSON.parse(foundCompanyFavicon.text); - t.is(foundCompanyFaviconRO.favicon.mimeType, 'image/png'); - t.is(foundCompanyFaviconRO.favicon.image.length > 0, true); - fs.writeFileSync(downloadedFaviconPatch, foundCompanyFaviconRO.favicon.image); - const isFileExists = fs.existsSync(downloadedFaviconPatch); - - t.is(isFileExists, true); - - // should return company favicon for simple user - - const foundCompanyFaviconForSimpleUser = await request(app.getHttpServer()) - .get(`/company/favicon/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', simpleUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyFaviconForSimpleUser.status, 200); - const foundCompanyFaviconForSimpleUserRO = JSON.parse(foundCompanyFaviconForSimpleUser.text); - t.is(foundCompanyFaviconForSimpleUserRO.favicon.mimeType, 'image/png'); - t.is(foundCompanyFaviconForSimpleUserRO.favicon.image.length > 0, true); - - const downloadedFaviconPatchForSimpleUser = join(os.tmpdir(), `${foundCompanyInfoRO.id}_simple_user_favicon.png`); - - fs.writeFileSync(downloadedFaviconPatchForSimpleUser, foundCompanyFaviconForSimpleUserRO.favicon.image); - const isFileExistsForSimpleUser = fs.existsSync(downloadedFaviconPatchForSimpleUser); - t.is(isFileExistsForSimpleUser, true); - - //should return favicon in full company info for admin - const foundCompanyInfoWithFavicon = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfoWithFavicon.status, 200); - const foundCompanyInfoWithFaviconRO = JSON.parse(foundCompanyInfoWithFavicon.text); - t.is(Object.hasOwn(foundCompanyInfoWithFaviconRO, 'favicon'), true); - t.is(foundCompanyInfoWithFaviconRO.favicon.mimeType, 'image/png'); - t.is(foundCompanyInfoWithFaviconRO.favicon.image.length > 0, true); - - const downloadedFaviconPatchWithFavicon = join( - os.tmpdir(), - `${foundCompanyInfoWithFaviconRO.id}_admin_user_favicon.png`, - ); - - fs.writeFileSync(downloadedFaviconPatchWithFavicon, foundCompanyInfoWithFaviconRO.favicon.image); - const isFileExistsWithFavicon = fs.existsSync(downloadedFaviconPatchWithFavicon); - t.is(isFileExistsWithFavicon, true); - - //should return favicon in full company info for simple user - const foundCompanyInfoWithFaviconForSimpleUser = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', simpleUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfoWithFaviconForSimpleUser.status, 200); - const foundCompanyInfoWithFaviconForSimpleUserRO = JSON.parse(foundCompanyInfoWithFaviconForSimpleUser.text); - t.is(Object.hasOwn(foundCompanyInfoWithFaviconForSimpleUserRO, 'favicon'), true); - t.is(foundCompanyInfoWithFaviconForSimpleUserRO.favicon.mimeType, 'image/png'); - t.is(foundCompanyInfoWithFaviconForSimpleUserRO.favicon.image.length > 0, true); - - const downloadedFaviconPatchForSimpleUserWithFavicon = join( - os.tmpdir(), - `${foundCompanyInfoWithFaviconForSimpleUserRO.id}_simple_user_favicon.png`, - ); - - fs.writeFileSync( - downloadedFaviconPatchForSimpleUserWithFavicon, - foundCompanyInfoWithFaviconForSimpleUserRO.favicon.image, - ); - const isFileExistsForSimpleUserWithFavicon = fs.existsSync(downloadedFaviconPatchForSimpleUserWithFavicon); - t.is(isFileExistsForSimpleUserWithFavicon, true); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + const testFaviconPatch = join(process.cwd(), 'test', 'ava-tests', 'test-files', 'test_logo.png'); + const downloadedFaviconPatch = join(os.tmpdir(), `${foundCompanyInfoRO.id}_test_favicon.png`); + + const createFaviconResponse = await request(app.getHttpServer()) + .post(`/company/favicon/${foundCompanyInfoRO.id}`) + .attach('file', testFaviconPatch) + .set('Content-Type', 'image/png') + .set('Cookie', adminUserToken) + .set('Accept', 'image/png'); + + const _createFaviconRO = JSON.parse(createFaviconResponse.text); + t.is(createFaviconResponse.status, 201); + + const foundCompanyFavicon = await request(app.getHttpServer()) + .get(`/company/favicon/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyFavicon.status, 200); + const foundCompanyFaviconRO = JSON.parse(foundCompanyFavicon.text); + t.is(foundCompanyFaviconRO.favicon.mimeType, 'image/png'); + t.is(foundCompanyFaviconRO.favicon.image.length > 0, true); + fs.writeFileSync(downloadedFaviconPatch, foundCompanyFaviconRO.favicon.image); + const isFileExists = fs.existsSync(downloadedFaviconPatch); + + t.is(isFileExists, true); + + // should return company favicon for simple user + + const foundCompanyFaviconForSimpleUser = await request(app.getHttpServer()) + .get(`/company/favicon/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', simpleUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyFaviconForSimpleUser.status, 200); + const foundCompanyFaviconForSimpleUserRO = JSON.parse(foundCompanyFaviconForSimpleUser.text); + t.is(foundCompanyFaviconForSimpleUserRO.favicon.mimeType, 'image/png'); + t.is(foundCompanyFaviconForSimpleUserRO.favicon.image.length > 0, true); + + const downloadedFaviconPatchForSimpleUser = join(os.tmpdir(), `${foundCompanyInfoRO.id}_simple_user_favicon.png`); + + fs.writeFileSync(downloadedFaviconPatchForSimpleUser, foundCompanyFaviconForSimpleUserRO.favicon.image); + const isFileExistsForSimpleUser = fs.existsSync(downloadedFaviconPatchForSimpleUser); + t.is(isFileExistsForSimpleUser, true); + + //should return favicon in full company info for admin + const foundCompanyInfoWithFavicon = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfoWithFavicon.status, 200); + const foundCompanyInfoWithFaviconRO = JSON.parse(foundCompanyInfoWithFavicon.text); + t.is(Object.hasOwn(foundCompanyInfoWithFaviconRO, 'favicon'), true); + t.is(foundCompanyInfoWithFaviconRO.favicon.mimeType, 'image/png'); + t.is(foundCompanyInfoWithFaviconRO.favicon.image.length > 0, true); + + const downloadedFaviconPatchWithFavicon = join( + os.tmpdir(), + `${foundCompanyInfoWithFaviconRO.id}_admin_user_favicon.png`, + ); + + fs.writeFileSync(downloadedFaviconPatchWithFavicon, foundCompanyInfoWithFaviconRO.favicon.image); + const isFileExistsWithFavicon = fs.existsSync(downloadedFaviconPatchWithFavicon); + t.is(isFileExistsWithFavicon, true); + + //should return favicon in full company info for simple user + const foundCompanyInfoWithFaviconForSimpleUser = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', simpleUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfoWithFaviconForSimpleUser.status, 200); + const foundCompanyInfoWithFaviconForSimpleUserRO = JSON.parse(foundCompanyInfoWithFaviconForSimpleUser.text); + t.is(Object.hasOwn(foundCompanyInfoWithFaviconForSimpleUserRO, 'favicon'), true); + t.is(foundCompanyInfoWithFaviconForSimpleUserRO.favicon.mimeType, 'image/png'); + t.is(foundCompanyInfoWithFaviconForSimpleUserRO.favicon.image.length > 0, true); + + const downloadedFaviconPatchForSimpleUserWithFavicon = join( + os.tmpdir(), + `${foundCompanyInfoWithFaviconForSimpleUserRO.id}_simple_user_favicon.png`, + ); + + fs.writeFileSync( + downloadedFaviconPatchForSimpleUserWithFavicon, + foundCompanyInfoWithFaviconForSimpleUserRO.favicon.image, + ); + const isFileExistsForSimpleUserWithFavicon = fs.existsSync(downloadedFaviconPatchForSimpleUserWithFavicon); + t.is(isFileExistsForSimpleUserWithFavicon, true); }); currentTest = 'POST & GET /company/tab-title/:companyId'; test.serial(`${currentTest} should create and return found company tab title after creation`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - const newTabTitle = `${faker.company.name()}_${faker.word.noun()}`; - const addCompanyTabTitleResponse = await request(app.getHttpServer()) - .post(`/company/tab-title/${foundCompanyInfoRO.id}`) - .send({ - tab_title: newTabTitle, - }) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(addCompanyTabTitleResponse.status, 201); - - const foundCompanyInfoAfterUpdate = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfoAfterUpdate.status, 200); - const foundCompanyInfoROAfterUpdate = JSON.parse(foundCompanyInfoAfterUpdate.text); - t.is(Object.hasOwn(foundCompanyInfoROAfterUpdate, 'tab_title'), true); - t.is(foundCompanyInfoROAfterUpdate.tab_title, newTabTitle); - - const foundCompanyTabTitle = await request(app.getHttpServer()) - .get(`/company/tab-title/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyTabTitle.status, 200); - const foundCompanyTabTitleRO = JSON.parse(foundCompanyTabTitle.text); - t.is(Object.hasOwn(foundCompanyTabTitleRO, 'tab_title'), true); - t.is(foundCompanyTabTitleRO.tab_title, newTabTitle); - - //should return tab title in full company info for simple user - - const foundCompanyTabTitleForSimpleUser = await request(app.getHttpServer()) - .get(`/company/tab-title/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', simpleUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyTabTitleForSimpleUser.status, 200); - const foundCompanyTabTitleForSimpleUserRO = JSON.parse(foundCompanyTabTitleForSimpleUser.text); - t.is(Object.hasOwn(foundCompanyTabTitleForSimpleUserRO, 'tab_title'), true); - t.is(foundCompanyTabTitleForSimpleUserRO.tab_title, newTabTitle); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + const newTabTitle = `${faker.company.name()}_${faker.word.noun()}`; + const addCompanyTabTitleResponse = await request(app.getHttpServer()) + .post(`/company/tab-title/${foundCompanyInfoRO.id}`) + .send({ + tab_title: newTabTitle, + }) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(addCompanyTabTitleResponse.status, 201); + + const foundCompanyInfoAfterUpdate = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfoAfterUpdate.status, 200); + const foundCompanyInfoROAfterUpdate = JSON.parse(foundCompanyInfoAfterUpdate.text); + t.is(Object.hasOwn(foundCompanyInfoROAfterUpdate, 'tab_title'), true); + t.is(foundCompanyInfoROAfterUpdate.tab_title, newTabTitle); + + const foundCompanyTabTitle = await request(app.getHttpServer()) + .get(`/company/tab-title/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyTabTitle.status, 200); + const foundCompanyTabTitleRO = JSON.parse(foundCompanyTabTitle.text); + t.is(Object.hasOwn(foundCompanyTabTitleRO, 'tab_title'), true); + t.is(foundCompanyTabTitleRO.tab_title, newTabTitle); + + //should return tab title in full company info for simple user + + const foundCompanyTabTitleForSimpleUser = await request(app.getHttpServer()) + .get(`/company/tab-title/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', simpleUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyTabTitleForSimpleUser.status, 200); + const foundCompanyTabTitleForSimpleUserRO = JSON.parse(foundCompanyTabTitleForSimpleUser.text); + t.is(Object.hasOwn(foundCompanyTabTitleForSimpleUserRO, 'tab_title'), true); + t.is(foundCompanyTabTitleForSimpleUserRO.tab_title, newTabTitle); }); currentTest = 'GET /company/white-label-properties/:companyId'; test.serial(`${currentTest} should return found company white label properties for company admin user`, async (t) => { - const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); - const { - connections, - firstTableInfo, - groups, - permissions, - secondTableInfo, - users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, - } = testData; - - const foundCompanyInfo = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyInfo.status, 200); - - const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); - - // crete company logo - const testLogoPatch = join(process.cwd(), 'test', 'ava-tests', 'test-files', 'test_logo.png'); - const _downloadedLogoPatch = join(os.tmpdir(), `${foundCompanyInfoRO.id}_test_logo.png`); - - const createLogoResponse = await request(app.getHttpServer()) - .post(`/company/logo/${foundCompanyInfoRO.id}`) - .attach('file', testLogoPatch) - .set('Content-Type', 'image/png') - .set('Cookie', adminUserToken) - .set('Accept', 'image/png'); - - const _createLogoRO = JSON.parse(createLogoResponse.text); - t.is(createLogoResponse.status, 201); - - // crete company favicon - const testFaviconPatch = join(process.cwd(), 'test', 'ava-tests', 'test-files', 'test_logo.png'); - const _downloadedFaviconPatch = join(os.tmpdir(), `${foundCompanyInfoRO.id}_test_favicon.png`); - - const createFaviconResponse = await request(app.getHttpServer()) - .post(`/company/favicon/${foundCompanyInfoRO.id}`) - .attach('file', testFaviconPatch) - .set('Content-Type', 'image/png') - .set('Cookie', adminUserToken) - .set('Accept', 'image/png'); - - const _createFaviconRO = JSON.parse(createFaviconResponse.text); - t.is(createFaviconResponse.status, 201); - - // crete company tab title - const newTabTitle = `${faker.company.name()}_${faker.word.noun()}`; - const addCompanyTabTitleResponse = await request(app.getHttpServer()) - .post(`/company/tab-title/${foundCompanyInfoRO.id}`) - .send({ - tab_title: newTabTitle, - }) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(addCompanyTabTitleResponse.status, 201); - - // should return all white label properties for company - - const foundCompanyWhiteLabelProperties = await request(app.getHttpServer()) - .get(`/company/white-label-properties/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', adminUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyWhiteLabelProperties.status, 200); - const foundCompanyWhiteLabelPropertiesRO = JSON.parse(foundCompanyWhiteLabelProperties.text); - t.is(Object.hasOwn(foundCompanyWhiteLabelPropertiesRO, 'logo'), true); - t.is(Object.hasOwn(foundCompanyWhiteLabelPropertiesRO, 'favicon'), true); - t.is(Object.hasOwn(foundCompanyWhiteLabelPropertiesRO, 'tab_title'), true); - t.is(foundCompanyWhiteLabelPropertiesRO.logo.mimeType, 'image/png'); - t.is(foundCompanyWhiteLabelPropertiesRO.logo.image.length > 0, true); - t.is(foundCompanyWhiteLabelPropertiesRO.favicon.mimeType, 'image/png'); - t.is(foundCompanyWhiteLabelPropertiesRO.favicon.image.length > 0, true); - t.is(foundCompanyWhiteLabelPropertiesRO.tab_title, newTabTitle); - - //should return all white label properties for simple user - - const foundCompanyWhiteLabelPropertiesForSimpleUser = await request(app.getHttpServer()) - .get(`/company/white-label-properties/${foundCompanyInfoRO.id}`) - .set('Content-Type', 'application/json') - .set('Cookie', simpleUserToken) - .set('Accept', 'application/json'); - - t.is(foundCompanyWhiteLabelPropertiesForSimpleUser.status, 200); - const foundCompanyWhiteLabelPropertiesForSimpleUserRO = JSON.parse( - foundCompanyWhiteLabelPropertiesForSimpleUser.text, - ); - t.is(Object.hasOwn(foundCompanyWhiteLabelPropertiesForSimpleUserRO, 'logo'), true); - t.is(Object.hasOwn(foundCompanyWhiteLabelPropertiesForSimpleUserRO, 'favicon'), true); - t.is(Object.hasOwn(foundCompanyWhiteLabelPropertiesForSimpleUserRO, 'tab_title'), true); - t.is(foundCompanyWhiteLabelPropertiesForSimpleUserRO.logo.mimeType, 'image/png'); - t.is(foundCompanyWhiteLabelPropertiesForSimpleUserRO.logo.image.length > 0, true); - t.is(foundCompanyWhiteLabelPropertiesForSimpleUserRO.favicon.mimeType, 'image/png'); - t.is(foundCompanyWhiteLabelPropertiesForSimpleUserRO.favicon.image.length > 0, true); - t.is(foundCompanyWhiteLabelPropertiesForSimpleUserRO.tab_title, newTabTitle); + const testData = await createConnectionsAndInviteNewUserInNewGroupWithGroupPermissions(app); + const { + connections, + firstTableInfo, + groups, + permissions, + secondTableInfo, + users: { adminUserToken, simpleUserToken, adminUserEmail, simpleUserEmail, simpleUserPassword }, + } = testData; + + const foundCompanyInfo = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyInfo.status, 200); + + const foundCompanyInfoRO = JSON.parse(foundCompanyInfo.text); + + // crete company logo + const testLogoPatch = join(process.cwd(), 'test', 'ava-tests', 'test-files', 'test_logo.png'); + const _downloadedLogoPatch = join(os.tmpdir(), `${foundCompanyInfoRO.id}_test_logo.png`); + + const createLogoResponse = await request(app.getHttpServer()) + .post(`/company/logo/${foundCompanyInfoRO.id}`) + .attach('file', testLogoPatch) + .set('Content-Type', 'image/png') + .set('Cookie', adminUserToken) + .set('Accept', 'image/png'); + + const _createLogoRO = JSON.parse(createLogoResponse.text); + t.is(createLogoResponse.status, 201); + + // crete company favicon + const testFaviconPatch = join(process.cwd(), 'test', 'ava-tests', 'test-files', 'test_logo.png'); + const _downloadedFaviconPatch = join(os.tmpdir(), `${foundCompanyInfoRO.id}_test_favicon.png`); + + const createFaviconResponse = await request(app.getHttpServer()) + .post(`/company/favicon/${foundCompanyInfoRO.id}`) + .attach('file', testFaviconPatch) + .set('Content-Type', 'image/png') + .set('Cookie', adminUserToken) + .set('Accept', 'image/png'); + + const _createFaviconRO = JSON.parse(createFaviconResponse.text); + t.is(createFaviconResponse.status, 201); + + // crete company tab title + const newTabTitle = `${faker.company.name()}_${faker.word.noun()}`; + const addCompanyTabTitleResponse = await request(app.getHttpServer()) + .post(`/company/tab-title/${foundCompanyInfoRO.id}`) + .send({ + tab_title: newTabTitle, + }) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(addCompanyTabTitleResponse.status, 201); + + // should return all white label properties for company + + const foundCompanyWhiteLabelProperties = await request(app.getHttpServer()) + .get(`/company/white-label-properties/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', adminUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyWhiteLabelProperties.status, 200); + const foundCompanyWhiteLabelPropertiesRO = JSON.parse(foundCompanyWhiteLabelProperties.text); + t.is(Object.hasOwn(foundCompanyWhiteLabelPropertiesRO, 'logo'), true); + t.is(Object.hasOwn(foundCompanyWhiteLabelPropertiesRO, 'favicon'), true); + t.is(Object.hasOwn(foundCompanyWhiteLabelPropertiesRO, 'tab_title'), true); + t.is(foundCompanyWhiteLabelPropertiesRO.logo.mimeType, 'image/png'); + t.is(foundCompanyWhiteLabelPropertiesRO.logo.image.length > 0, true); + t.is(foundCompanyWhiteLabelPropertiesRO.favicon.mimeType, 'image/png'); + t.is(foundCompanyWhiteLabelPropertiesRO.favicon.image.length > 0, true); + t.is(foundCompanyWhiteLabelPropertiesRO.tab_title, newTabTitle); + + //should return all white label properties for simple user + + const foundCompanyWhiteLabelPropertiesForSimpleUser = await request(app.getHttpServer()) + .get(`/company/white-label-properties/${foundCompanyInfoRO.id}`) + .set('Content-Type', 'application/json') + .set('Cookie', simpleUserToken) + .set('Accept', 'application/json'); + + t.is(foundCompanyWhiteLabelPropertiesForSimpleUser.status, 200); + const foundCompanyWhiteLabelPropertiesForSimpleUserRO = JSON.parse( + foundCompanyWhiteLabelPropertiesForSimpleUser.text, + ); + t.is(Object.hasOwn(foundCompanyWhiteLabelPropertiesForSimpleUserRO, 'logo'), true); + t.is(Object.hasOwn(foundCompanyWhiteLabelPropertiesForSimpleUserRO, 'favicon'), true); + t.is(Object.hasOwn(foundCompanyWhiteLabelPropertiesForSimpleUserRO, 'tab_title'), true); + t.is(foundCompanyWhiteLabelPropertiesForSimpleUserRO.logo.mimeType, 'image/png'); + t.is(foundCompanyWhiteLabelPropertiesForSimpleUserRO.logo.image.length > 0, true); + t.is(foundCompanyWhiteLabelPropertiesForSimpleUserRO.favicon.mimeType, 'image/png'); + t.is(foundCompanyWhiteLabelPropertiesForSimpleUserRO.favicon.image.length > 0, true); + t.is(foundCompanyWhiteLabelPropertiesForSimpleUserRO.tab_title, newTabTitle); }); diff --git a/backend/test/ava-tests/saas-tests/table-cassandra-agent.e2e.test.ts b/backend/test/ava-tests/saas-tests/table-cassandra-agent.e2e.test.ts index d27d0c479..1559b93f9 100644 --- a/backend/test/ava-tests/saas-tests/table-cassandra-agent.e2e.test.ts +++ b/backend/test/ava-tests/saas-tests/table-cassandra-agent.e2e.test.ts @@ -13,6 +13,7 @@ import path, { join } from 'path'; import request from 'supertest'; import { fileURLToPath } from 'url'; import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; import { LogOperationTypeEnum, QueryOrderingEnum } from '../../../src/enums/index.js'; import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; @@ -25,9 +26,9 @@ import { MockFactory } from '../../mock.factory.js'; import { createTestTable } from '../../utils/create-test-table.js'; import { getTestData } from '../../utils/get-test-data.js'; import { registerUserAndReturnUserInfo } from '../../utils/register-user-and-return-user-info.js'; -import { TestUtils } from '../../utils/test.utils.js'; import { setSaasEnvVariable } from '../../utils/set-saas-env-variable.js'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; +import { TestUtils } from '../../utils/test.utils.js'; + const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); diff --git a/backend/test/ava-tests/saas-tests/table-clickhouse-agent-e2e.test.ts b/backend/test/ava-tests/saas-tests/table-clickhouse-agent-e2e.test.ts index 96e059431..b8ad1e820 100644 --- a/backend/test/ava-tests/saas-tests/table-clickhouse-agent-e2e.test.ts +++ b/backend/test/ava-tests/saas-tests/table-clickhouse-agent-e2e.test.ts @@ -13,6 +13,7 @@ import path, { join } from 'path'; import request from 'supertest'; import { fileURLToPath } from 'url'; import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; import { LogOperationTypeEnum, QueryOrderingEnum } from '../../../src/enums/index.js'; import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; @@ -26,7 +27,6 @@ import { createTestTable } from '../../utils/create-test-table.js'; import { getTestData } from '../../utils/get-test-data.js'; import { registerUserAndReturnUserInfo } from '../../utils/register-user-and-return-user-info.js'; import { TestUtils } from '../../utils/test.utils.js'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); diff --git a/backend/test/ava-tests/saas-tests/table-clickhouse-e2e.test.ts b/backend/test/ava-tests/saas-tests/table-clickhouse-e2e.test.ts index b33437689..1dbf4c508 100644 --- a/backend/test/ava-tests/saas-tests/table-clickhouse-e2e.test.ts +++ b/backend/test/ava-tests/saas-tests/table-clickhouse-e2e.test.ts @@ -13,6 +13,7 @@ import path, { join } from 'path'; import request from 'supertest'; import { fileURLToPath } from 'url'; import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; import { LogOperationTypeEnum, QueryOrderingEnum } from '../../../src/enums/index.js'; import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; @@ -26,7 +27,6 @@ import { createTestTable } from '../../utils/create-test-table.js'; import { getTestData } from '../../utils/get-test-data.js'; import { registerUserAndReturnUserInfo } from '../../utils/register-user-and-return-user-info.js'; import { TestUtils } from '../../utils/test.utils.js'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); diff --git a/backend/test/ava-tests/saas-tests/table-ibmdb2-agent-e2e.test.ts b/backend/test/ava-tests/saas-tests/table-ibmdb2-agent-e2e.test.ts index 809247e41..5206df4e6 100644 --- a/backend/test/ava-tests/saas-tests/table-ibmdb2-agent-e2e.test.ts +++ b/backend/test/ava-tests/saas-tests/table-ibmdb2-agent-e2e.test.ts @@ -4,11 +4,18 @@ import { faker } from '@faker-js/faker'; import { INestApplication, ValidationPipe } from '@nestjs/common'; import { Test } from '@nestjs/testing'; import test from 'ava'; +import { ValidationError } from 'class-validator'; import cookieParser from 'cookie-parser'; +import fs from 'fs'; +import os from 'os'; +import path, { join } from 'path'; import request from 'supertest'; +import { fileURLToPath } from 'url'; import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; import { LogOperationTypeEnum, QueryOrderingEnum } from '../../../src/enums/index.js'; import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; +import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; import { Messages } from '../../../src/exceptions/text/messages.js'; import { Cacher } from '../../../src/helpers/cache/cacher.js'; import { Constants } from '../../../src/helpers/constants/constants.js'; @@ -19,14 +26,6 @@ import { createTestTable } from '../../utils/create-test-table.js'; import { getTestData } from '../../utils/get-test-data.js'; import { registerUserAndReturnUserInfo } from '../../utils/register-user-and-return-user-info.js'; import { TestUtils } from '../../utils/test.utils.js'; -import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; -import { ValidationError } from 'class-validator'; -import fs from 'fs'; -import os from 'os'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import { join } from 'path'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); diff --git a/backend/test/ava-tests/saas-tests/table-mongodb-agent-e2e.test.ts b/backend/test/ava-tests/saas-tests/table-mongodb-agent-e2e.test.ts index cb3ae234c..dbf652c8f 100644 --- a/backend/test/ava-tests/saas-tests/table-mongodb-agent-e2e.test.ts +++ b/backend/test/ava-tests/saas-tests/table-mongodb-agent-e2e.test.ts @@ -4,12 +4,20 @@ import { faker } from '@faker-js/faker'; import { INestApplication, ValidationPipe } from '@nestjs/common'; import { Test } from '@nestjs/testing'; import test from 'ava'; +import { ValidationError } from 'class-validator'; import cookieParser from 'cookie-parser'; +import fs from 'fs'; +import os from 'os'; +import path, { join } from 'path'; import request from 'supertest'; +import { fileURLToPath } from 'url'; import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; import { LogOperationTypeEnum, QueryOrderingEnum } from '../../../src/enums/index.js'; import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; +import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; import { Messages } from '../../../src/exceptions/text/messages.js'; +import { Cacher } from '../../../src/helpers/cache/cacher.js'; import { Constants } from '../../../src/helpers/constants/constants.js'; import { DatabaseModule } from '../../../src/shared/database/database.module.js'; import { DatabaseService } from '../../../src/shared/database/database.service.js'; @@ -18,15 +26,6 @@ import { createTestTable } from '../../utils/create-test-table.js'; import { getTestData } from '../../utils/get-test-data.js'; import { registerUserAndReturnUserInfo } from '../../utils/register-user-and-return-user-info.js'; import { TestUtils } from '../../utils/test.utils.js'; -import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; -import { ValidationError } from 'class-validator'; -import fs from 'fs'; -import os from 'os'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import { join } from 'path'; -import { Cacher } from '../../../src/helpers/cache/cacher.js'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); diff --git a/backend/test/ava-tests/saas-tests/table-mssql-agent-e2e.test.ts b/backend/test/ava-tests/saas-tests/table-mssql-agent-e2e.test.ts index 30619f2b2..11eac3fc0 100644 --- a/backend/test/ava-tests/saas-tests/table-mssql-agent-e2e.test.ts +++ b/backend/test/ava-tests/saas-tests/table-mssql-agent-e2e.test.ts @@ -4,32 +4,31 @@ import { faker } from '@faker-js/faker'; import { INestApplication, ValidationPipe } from '@nestjs/common'; import { Test } from '@nestjs/testing'; +import { ERROR_MESSAGES } from '@rocketadmin/shared-code/dist/src/helpers/errors/error-messages.js'; import test from 'ava'; +import { ValidationError } from 'class-validator'; import cookieParser from 'cookie-parser'; +import fs from 'fs'; +import knex from 'knex'; +import os from 'os'; +import path, { join } from 'path'; import request from 'supertest'; +import { fileURLToPath } from 'url'; import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; import { LogOperationTypeEnum, QueryOrderingEnum } from '../../../src/enums/index.js'; import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; +import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; import { Messages } from '../../../src/exceptions/text/messages.js'; +import { Cacher } from '../../../src/helpers/cache/cacher.js'; import { Constants } from '../../../src/helpers/constants/constants.js'; import { DatabaseModule } from '../../../src/shared/database/database.module.js'; import { DatabaseService } from '../../../src/shared/database/database.service.js'; import { MockFactory } from '../../mock.factory.js'; +import { getRandomTestTableName } from '../../utils/get-random-test-table-name.js'; import { getTestData } from '../../utils/get-test-data.js'; import { registerUserAndReturnUserInfo } from '../../utils/register-user-and-return-user-info.js'; import { TestUtils } from '../../utils/test.utils.js'; -import knex from 'knex'; -import { getRandomTestTableName } from '../../utils/get-random-test-table-name.js'; -import { ERROR_MESSAGES } from '@rocketadmin/shared-code/dist/src/helpers/errors/error-messages.js'; -import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; -import { ValidationError } from 'class-validator'; -import fs from 'fs'; -import os from 'os'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import { join } from 'path'; -import { Cacher } from '../../../src/helpers/cache/cacher.js'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); diff --git a/backend/test/ava-tests/saas-tests/table-mysql-agent-e2e.test.ts b/backend/test/ava-tests/saas-tests/table-mysql-agent-e2e.test.ts index d0c102f31..3b33b1d8e 100644 --- a/backend/test/ava-tests/saas-tests/table-mysql-agent-e2e.test.ts +++ b/backend/test/ava-tests/saas-tests/table-mysql-agent-e2e.test.ts @@ -4,32 +4,31 @@ import { faker } from '@faker-js/faker'; import { INestApplication, ValidationPipe } from '@nestjs/common'; import { Test } from '@nestjs/testing'; +import { ERROR_MESSAGES } from '@rocketadmin/shared-code/dist/src/helpers/errors/error-messages.js'; import test from 'ava'; +import { ValidationError } from 'class-validator'; import cookieParser from 'cookie-parser'; +import fs from 'fs'; +import knex from 'knex'; +import os from 'os'; +import path, { join } from 'path'; import request from 'supertest'; +import { fileURLToPath } from 'url'; import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; import { LogOperationTypeEnum, QueryOrderingEnum } from '../../../src/enums/index.js'; import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; +import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; import { Messages } from '../../../src/exceptions/text/messages.js'; +import { Cacher } from '../../../src/helpers/cache/cacher.js'; import { Constants } from '../../../src/helpers/constants/constants.js'; import { DatabaseModule } from '../../../src/shared/database/database.module.js'; import { DatabaseService } from '../../../src/shared/database/database.service.js'; import { MockFactory } from '../../mock.factory.js'; +import { getRandomConstraintName, getRandomTestTableName } from '../../utils/get-random-test-table-name.js'; import { getTestData } from '../../utils/get-test-data.js'; import { registerUserAndReturnUserInfo } from '../../utils/register-user-and-return-user-info.js'; import { TestUtils } from '../../utils/test.utils.js'; -import knex from 'knex'; -import { getRandomConstraintName, getRandomTestTableName } from '../../utils/get-random-test-table-name.js'; -import { ERROR_MESSAGES } from '@rocketadmin/shared-code/dist/src/helpers/errors/error-messages.js'; -import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; -import { ValidationError } from 'class-validator'; -import fs from 'fs'; -import os from 'os'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import { join } from 'path'; -import { Cacher } from '../../../src/helpers/cache/cacher.js'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); diff --git a/backend/test/ava-tests/saas-tests/table-oracle-agent-e2e.test.ts b/backend/test/ava-tests/saas-tests/table-oracle-agent-e2e.test.ts index 02194613e..5bf63932f 100644 --- a/backend/test/ava-tests/saas-tests/table-oracle-agent-e2e.test.ts +++ b/backend/test/ava-tests/saas-tests/table-oracle-agent-e2e.test.ts @@ -4,32 +4,31 @@ import { faker } from '@faker-js/faker'; import { INestApplication, ValidationPipe } from '@nestjs/common'; import { Test } from '@nestjs/testing'; +import { ERROR_MESSAGES } from '@rocketadmin/shared-code/dist/src/helpers/errors/error-messages.js'; import test from 'ava'; +import { ValidationError } from 'class-validator'; import cookieParser from 'cookie-parser'; +import fs from 'fs'; +import knex from 'knex'; +import os from 'os'; +import path, { join } from 'path'; import request from 'supertest'; +import { fileURLToPath } from 'url'; import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; import { LogOperationTypeEnum, QueryOrderingEnum } from '../../../src/enums/index.js'; import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; +import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; import { Messages } from '../../../src/exceptions/text/messages.js'; +import { Cacher } from '../../../src/helpers/cache/cacher.js'; import { Constants } from '../../../src/helpers/constants/constants.js'; import { DatabaseModule } from '../../../src/shared/database/database.module.js'; import { DatabaseService } from '../../../src/shared/database/database.service.js'; import { MockFactory } from '../../mock.factory.js'; +import { getRandomConstraintName, getRandomTestTableName } from '../../utils/get-random-test-table-name.js'; import { getTestData } from '../../utils/get-test-data.js'; import { registerUserAndReturnUserInfo } from '../../utils/register-user-and-return-user-info.js'; import { TestUtils } from '../../utils/test.utils.js'; -import knex from 'knex'; -import { getRandomConstraintName, getRandomTestTableName } from '../../utils/get-random-test-table-name.js'; -import { ERROR_MESSAGES } from '@rocketadmin/shared-code/dist/src/helpers/errors/error-messages.js'; -import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; -import { ValidationError } from 'class-validator'; -import fs from 'fs'; -import os from 'os'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import { join } from 'path'; -import { Cacher } from '../../../src/helpers/cache/cacher.js'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); diff --git a/backend/test/ava-tests/saas-tests/table-postgres-agent-e2e.test.ts b/backend/test/ava-tests/saas-tests/table-postgres-agent-e2e.test.ts index 41ce3fbea..79c95f216 100644 --- a/backend/test/ava-tests/saas-tests/table-postgres-agent-e2e.test.ts +++ b/backend/test/ava-tests/saas-tests/table-postgres-agent-e2e.test.ts @@ -4,32 +4,31 @@ import { faker } from '@faker-js/faker'; import { INestApplication, ValidationPipe } from '@nestjs/common'; import { Test } from '@nestjs/testing'; +import { ERROR_MESSAGES } from '@rocketadmin/shared-code/dist/src/helpers/errors/error-messages.js'; import test from 'ava'; +import { ValidationError } from 'class-validator'; import cookieParser from 'cookie-parser'; +import fs from 'fs'; +import knex from 'knex'; +import os from 'os'; +import path, { join } from 'path'; import request from 'supertest'; +import { fileURLToPath } from 'url'; import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; import { LogOperationTypeEnum, QueryOrderingEnum } from '../../../src/enums/index.js'; import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; +import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; import { Messages } from '../../../src/exceptions/text/messages.js'; +import { Cacher } from '../../../src/helpers/cache/cacher.js'; import { Constants } from '../../../src/helpers/constants/constants.js'; import { DatabaseModule } from '../../../src/shared/database/database.module.js'; import { DatabaseService } from '../../../src/shared/database/database.service.js'; import { MockFactory } from '../../mock.factory.js'; +import { getRandomConstraintName, getRandomTestTableName } from '../../utils/get-random-test-table-name.js'; import { getTestData } from '../../utils/get-test-data.js'; import { registerUserAndReturnUserInfo } from '../../utils/register-user-and-return-user-info.js'; import { TestUtils } from '../../utils/test.utils.js'; -import knex from 'knex'; -import { getRandomConstraintName, getRandomTestTableName } from '../../utils/get-random-test-table-name.js'; -import { ERROR_MESSAGES } from '@rocketadmin/shared-code/dist/src/helpers/errors/error-messages.js'; -import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; -import { ValidationError } from 'class-validator'; -import fs from 'fs'; -import os from 'os'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import { join } from 'path'; -import { Cacher } from '../../../src/helpers/cache/cacher.js'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); diff --git a/backend/test/ava-tests/saas-tests/table-postgres-e2e.test.ts b/backend/test/ava-tests/saas-tests/table-postgres-e2e.test.ts index 74a2ad9e7..279e56381 100644 --- a/backend/test/ava-tests/saas-tests/table-postgres-e2e.test.ts +++ b/backend/test/ava-tests/saas-tests/table-postgres-e2e.test.ts @@ -13,6 +13,7 @@ import path, { join } from 'path'; import request from 'supertest'; import { fileURLToPath } from 'url'; import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; import { LogOperationTypeEnum, QueryOrderingEnum } from '../../../src/enums/index.js'; import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; @@ -23,12 +24,11 @@ import { DatabaseModule } from '../../../src/shared/database/database.module.js' import { DatabaseService } from '../../../src/shared/database/database.service.js'; import { MockFactory } from '../../mock.factory.js'; import { createTestTable } from '../../utils/create-test-table.js'; +import { getRandomTestTableName } from '../../utils/get-random-test-table-name.js'; import { getTestData } from '../../utils/get-test-data.js'; +import { getTestKnex } from '../../utils/get-test-knex.js'; import { registerUserAndReturnUserInfo } from '../../utils/register-user-and-return-user-info.js'; import { TestUtils } from '../../utils/test.utils.js'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; -import { getTestKnex } from '../../utils/get-test-knex.js'; -import { getRandomTestTableName } from '../../utils/get-random-test-table-name.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -789,9 +789,9 @@ should return all found rows with sorting ids by DESC`, t.is(getTableRowsResponse.status, 200); t.is(typeof getTableRowsRO, 'object'); - t.is(getTableRowsRO.hasOwnProperty('rows'), true); - t.is(getTableRowsRO.hasOwnProperty('primaryColumns'), true); - t.is(getTableRowsRO.hasOwnProperty('pagination'), true); + t.is(Object.hasOwn(getTableRowsRO, 'rows'), true); + t.is(Object.hasOwn(getTableRowsRO, 'primaryColumns'), true); + t.is(Object.hasOwn(getTableRowsRO, 'pagination'), true); t.is(getTableRowsRO.rows.length, 20); t.is(Object.keys(getTableRowsRO.rows[1]).length, 5); t.is(getTableRowsRO.rows[0].id, 42); @@ -799,8 +799,8 @@ should return all found rows with sorting ids by DESC`, t.is(getTableRowsRO.rows[19].id, 23); t.is(typeof getTableRowsRO.primaryColumns, 'object'); - t.is(getTableRowsRO.primaryColumns[0].hasOwnProperty('column_name'), true); - t.is(getTableRowsRO.primaryColumns[0].hasOwnProperty('data_type'), true); + t.is(Object.hasOwn(getTableRowsRO.primaryColumns[0], 'column_name'), true); + t.is(Object.hasOwn(getTableRowsRO.primaryColumns[0], 'data_type'), true); } catch (e) { console.error(e); throw e; diff --git a/backend/test/ava-tests/saas-tests/user-e2e.test.ts b/backend/test/ava-tests/saas-tests/user-e2e.test.ts index d644c158e..4ca5089f8 100644 --- a/backend/test/ava-tests/saas-tests/user-e2e.test.ts +++ b/backend/test/ava-tests/saas-tests/user-e2e.test.ts @@ -7,24 +7,24 @@ import { ValidationError } from 'class-validator'; import cookieParser from 'cookie-parser'; import request from 'supertest'; import { ApplicationModule } from '../../../src/app.module.js'; +import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; import { IUserInfo } from '../../../src/entities/user/user.interface.js'; import { AllExceptionsFilter } from '../../../src/exceptions/all-exceptions.filter.js'; import { ValidationException } from '../../../src/exceptions/custom-exceptions/validation-exception.js'; import { Messages } from '../../../src/exceptions/text/messages.js'; +import { Cacher } from '../../../src/helpers/cache/cacher.js'; +import { Constants } from '../../../src/helpers/constants/constants.js'; import { DatabaseModule } from '../../../src/shared/database/database.module.js'; import { DatabaseService } from '../../../src/shared/database/database.service.js'; +import { MockFactory } from '../../mock.factory.js'; +import { createTestTable } from '../../utils/create-test-table.js'; +import { getTestData } from '../../utils/get-test-data.js'; import { - registerUserAndReturnUserInfo, - registerUserOnSaasAndReturnUserInfo, + registerUserAndReturnUserInfo, + registerUserOnSaasAndReturnUserInfo, } from '../../utils/register-user-and-return-user-info.js'; import { sendRequestToSaasPart } from '../../utils/send-request-to-saas-part.util.js'; import { TestUtils } from '../../utils/test.utils.js'; -import { Cacher } from '../../../src/helpers/cache/cacher.js'; -import { Constants } from '../../../src/helpers/constants/constants.js'; -import { getTestData } from '../../utils/get-test-data.js'; -import { createTestTable } from '../../utils/create-test-table.js'; -import { MockFactory } from '../../mock.factory.js'; -import { WinstonLogger } from '../../../src/entities/logging/winston-logger.js'; let app: INestApplication; let currentTest: string; @@ -33,503 +33,503 @@ let _testUtils: TestUtils; const mockFactory = new MockFactory(); test.before(async () => { - const moduleFixture = await Test.createTestingModule({ - imports: [ApplicationModule, DatabaseModule], - providers: [DatabaseService, TestUtils], - }).compile(); - app = moduleFixture.createNestApplication(); - _testUtils = moduleFixture.get(TestUtils); - - app.use(cookieParser()); - app.useGlobalFilters(new AllExceptionsFilter(app.get(WinstonLogger))); - app.useGlobalPipes( - new ValidationPipe({ - exceptionFactory(validationErrors: ValidationError[] = []) { - return new ValidationException(validationErrors); - }, - }), - ); - await app.init(); - app.getHttpServer().listen(0); + const moduleFixture = await Test.createTestingModule({ + imports: [ApplicationModule, DatabaseModule], + providers: [DatabaseService, TestUtils], + }).compile(); + app = moduleFixture.createNestApplication(); + _testUtils = moduleFixture.get(TestUtils); + + app.use(cookieParser()); + app.useGlobalFilters(new AllExceptionsFilter(app.get(WinstonLogger))); + app.useGlobalPipes( + new ValidationPipe({ + exceptionFactory(validationErrors: ValidationError[] = []) { + return new ValidationException(validationErrors); + }, + }), + ); + await app.init(); + app.getHttpServer().listen(0); }); test.after(async () => { - try { - await Cacher.clearAllCache(); - await app.close(); - } catch (e) { - console.error('After tests error ' + e); - } + try { + await Cacher.clearAllCache(); + await app.close(); + } catch (e) { + console.error('After tests error ' + e); + } }); currentTest = 'GET /user'; test.serial(`${currentTest} should user info for this user`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { token } = adminUserRegisterInfo; - - const getUserResult = await request(app.getHttpServer()) - .get('/user') - .set('Content-Type', 'application/json') - .set('Cookie', token) - .set('Accept', 'application/json'); - const getUserRO: IUserInfo = JSON.parse(getUserResult.text); - - t.is(getUserRO.isActive, false); - t.is(getUserRO.email, adminUserRegisterInfo.email.toLowerCase()); - t.is(Object.hasOwn(getUserRO, 'createdAt'), true); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { token } = adminUserRegisterInfo; + + const getUserResult = await request(app.getHttpServer()) + .get('/user') + .set('Content-Type', 'application/json') + .set('Cookie', token) + .set('Accept', 'application/json'); + const getUserRO: IUserInfo = JSON.parse(getUserResult.text); + + t.is(getUserRO.isActive, false); + t.is(getUserRO.email, adminUserRegisterInfo.email.toLowerCase()); + t.is(Object.hasOwn(getUserRO, 'createdAt'), true); + t.pass(); }); currentTest = 'DELETE /user'; test.serial(`${currentTest} should return user deletion result`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { token } = adminUserRegisterInfo; - - let getUserResult = await request(app.getHttpServer()) - .get('/user') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - t.is(getUserResult.status, 200); - const deleteUserResult = await request(app.getHttpServer()) - .put('/user/delete/') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const deleteUserRO = JSON.parse(deleteUserResult.text); - t.is(deleteUserRO.email, adminUserRegisterInfo.email.toLowerCase()); - getUserResult = await request(app.getHttpServer()) - .get('/user') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - t.is(getUserResult.status, 401); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { token } = adminUserRegisterInfo; + + let getUserResult = await request(app.getHttpServer()) + .get('/user') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + t.is(getUserResult.status, 200); + const deleteUserResult = await request(app.getHttpServer()) + .put('/user/delete/') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const deleteUserRO = JSON.parse(deleteUserResult.text); + t.is(deleteUserRO.email, adminUserRegisterInfo.email.toLowerCase()); + getUserResult = await request(app.getHttpServer()) + .get('/user') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + t.is(getUserResult.status, 401); + t.pass(); }); currentTest = 'POST /user/login'; test.serial(`${currentTest} should return expiration token when user login`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { email, password } = adminUserRegisterInfo; - - const loginUserResult = await request(app.getHttpServer()) - .post('/user/login/') - .send({ email, password }) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const loginUserRO = JSON.parse(loginUserResult.text); - t.is(Object.hasOwn(loginUserRO, 'expires'), true); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { email, password } = adminUserRegisterInfo; + + const loginUserResult = await request(app.getHttpServer()) + .post('/user/login/') + .send({ email, password }) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const loginUserRO = JSON.parse(loginUserResult.text); + t.is(Object.hasOwn(loginUserRO, 'expires'), true); + t.pass(); }); test.serial(`${currentTest} should return expiration token when user login with company id`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { email, password } = adminUserRegisterInfo; - - const foundCompanyInfos = await request(app.getHttpServer()) - .get(`/company/my/email/${email}`) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const foundCompanyInfosRO = JSON.parse(foundCompanyInfos.text); - - const loginBodyRequest = { - email, - password, - companyId: foundCompanyInfosRO[0].id, - }; - const loginUserResult = await request(app.getHttpServer()) - .post('/user/login/') - .send(loginBodyRequest) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const loginUserRO = JSON.parse(loginUserResult.text); - t.is(Object.hasOwn(loginUserRO, 'expires'), true); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { email, password } = adminUserRegisterInfo; + + const foundCompanyInfos = await request(app.getHttpServer()) + .get(`/company/my/email/${email}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const foundCompanyInfosRO = JSON.parse(foundCompanyInfos.text); + + const loginBodyRequest = { + email, + password, + companyId: foundCompanyInfosRO[0].id, + }; + const loginUserResult = await request(app.getHttpServer()) + .post('/user/login/') + .send(loginBodyRequest) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const loginUserRO = JSON.parse(loginUserResult.text); + t.is(Object.hasOwn(loginUserRO, 'expires'), true); + t.pass(); }); test.serial( - `${currentTest} should return expiration token when user login with company id and have more than one company`, - async (t) => { - const testEmail = 'test@mail.com'; - const testData_1 = await registerUserOnSaasAndReturnUserInfo(testEmail); - const _testData_2 = await registerUserOnSaasAndReturnUserInfo(testEmail); - - const foundCompanyInfos = await request(app.getHttpServer()) - .get(`/company/my/email/${testEmail}`) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const foundCompanyInfosRO = JSON.parse(foundCompanyInfos.text); - - const loginBodyRequest = { - email: testEmail, - password: testData_1.password, - companyId: foundCompanyInfosRO[0].id, - }; - - const loginUserResult = await request(app.getHttpServer()) - .post('/user/login/') - .send(loginBodyRequest) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const loginUserRO = JSON.parse(loginUserResult.text); - t.is(loginUserResult.status, 201); - t.is(Object.hasOwn(loginUserRO, 'expires'), true); - t.pass(); - }, + `${currentTest} should return expiration token when user login with company id and have more than one company`, + async (t) => { + const testEmail = 'test@mail.com'; + const testData_1 = await registerUserOnSaasAndReturnUserInfo(testEmail); + const _testData_2 = await registerUserOnSaasAndReturnUserInfo(testEmail); + + const foundCompanyInfos = await request(app.getHttpServer()) + .get(`/company/my/email/${testEmail}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const foundCompanyInfosRO = JSON.parse(foundCompanyInfos.text); + + const loginBodyRequest = { + email: testEmail, + password: testData_1.password, + companyId: foundCompanyInfosRO[0].id, + }; + + const loginUserResult = await request(app.getHttpServer()) + .post('/user/login/') + .send(loginBodyRequest) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const loginUserRO = JSON.parse(loginUserResult.text); + t.is(loginUserResult.status, 201); + t.is(Object.hasOwn(loginUserRO, 'expires'), true); + t.pass(); + }, ); test.serial( - `${currentTest} should throw an error when user login without company id with more than one company`, - async (t) => { - const testEmail = 'test@mail.com'; - const testData_1 = await registerUserOnSaasAndReturnUserInfo(testEmail); - const _testData_2 = await registerUserOnSaasAndReturnUserInfo(testEmail); - - const _foundCompanyInfos = await request(app.getHttpServer()) - .get(`/company/my/email/${testEmail}`) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const loginBodyRequest = { - email: testEmail, - password: testData_1.password, - }; - - const loginUserResult = await request(app.getHttpServer()) - .post('/user/login/') - .send(loginBodyRequest) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const loginUserRO = JSON.parse(loginUserResult.text); - t.is(loginUserResult.status, 400); - t.is(loginUserRO.message, Messages.LOGIN_DENIED_SHOULD_CHOOSE_COMPANY); - t.pass(); - }, + `${currentTest} should throw an error when user login without company id with more than one company`, + async (t) => { + const testEmail = 'test@mail.com'; + const testData_1 = await registerUserOnSaasAndReturnUserInfo(testEmail); + const _testData_2 = await registerUserOnSaasAndReturnUserInfo(testEmail); + + const _foundCompanyInfos = await request(app.getHttpServer()) + .get(`/company/my/email/${testEmail}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const loginBodyRequest = { + email: testEmail, + password: testData_1.password, + }; + + const loginUserResult = await request(app.getHttpServer()) + .post('/user/login/') + .send(loginBodyRequest) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const loginUserRO = JSON.parse(loginUserResult.text); + t.is(loginUserResult.status, 400); + t.is(loginUserRO.message, Messages.LOGIN_DENIED_SHOULD_CHOOSE_COMPANY); + t.pass(); + }, ); test.serial(`${currentTest} reject authorization when try to login with wrong password`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { email, password } = adminUserRegisterInfo; - - const realPassword = password; - const wrongPassword = 'wrong password'; - const wrongUserLogin = await request(app.getHttpServer()) - .post('/user/login/') - .send({ email, password: wrongPassword }) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - t.is(wrongUserLogin.status, 400); - - const loginUserResult = await request(app.getHttpServer()) - .post('/user/login/') - .send({ email, password: realPassword }) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const loginUserRO = JSON.parse(loginUserResult.text); - t.is(Object.hasOwn(loginUserRO, 'expires'), true); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { email, password } = adminUserRegisterInfo; + + const realPassword = password; + const wrongPassword = 'wrong password'; + const wrongUserLogin = await request(app.getHttpServer()) + .post('/user/login/') + .send({ email, password: wrongPassword }) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + t.is(wrongUserLogin.status, 400); + + const loginUserResult = await request(app.getHttpServer()) + .post('/user/login/') + .send({ email, password: realPassword }) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const loginUserRO = JSON.parse(loginUserResult.text); + t.is(Object.hasOwn(loginUserRO, 'expires'), true); + t.pass(); }); currentTest = 'POST /user/settings'; test.serial(`${currentTest} should return created user settings`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { token } = adminUserRegisterInfo; - - const settings = JSON.stringify({ test: 'test' }); - - const saveUserSettingsResult = await request(app.getHttpServer()) - .post('/user/settings') - .send({ userSettings: settings }) - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - t.is(saveUserSettingsResult.status, 201); - const saveUserSettingsRO = JSON.parse(saveUserSettingsResult.text); - t.is(Object.hasOwn(saveUserSettingsRO, 'userSettings'), true); - t.is(JSON.parse(saveUserSettingsRO.userSettings).test, 'test'); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { token } = adminUserRegisterInfo; + + const settings = JSON.stringify({ test: 'test' }); + + const saveUserSettingsResult = await request(app.getHttpServer()) + .post('/user/settings') + .send({ userSettings: settings }) + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + t.is(saveUserSettingsResult.status, 201); + const saveUserSettingsRO = JSON.parse(saveUserSettingsResult.text); + t.is(Object.hasOwn(saveUserSettingsRO, 'userSettings'), true); + t.is(JSON.parse(saveUserSettingsRO.userSettings).test, 'test'); + t.pass(); }); currentTest = 'GET /user/settings'; test.serial(`${currentTest} should return empty user settings when it was not created`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { token } = adminUserRegisterInfo; - - const getUserSettingsResult = await request(app.getHttpServer()) - .get('/user/settings') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const getUserSettingsRO = JSON.parse(getUserSettingsResult.text); - t.is(getUserSettingsResult.status, 200); - t.is(Object.hasOwn(getUserSettingsRO, 'userSettings'), true); - t.is(getUserSettingsRO.userSettings, null); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { token } = adminUserRegisterInfo; + + const getUserSettingsResult = await request(app.getHttpServer()) + .get('/user/settings') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const getUserSettingsRO = JSON.parse(getUserSettingsResult.text); + t.is(getUserSettingsResult.status, 200); + t.is(Object.hasOwn(getUserSettingsRO, 'userSettings'), true); + t.is(getUserSettingsRO.userSettings, null); + t.pass(); }); test.serial(`${currentTest} should return user settings when it was created`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { token } = adminUserRegisterInfo; - - const settings = JSON.stringify({ test: 'test' }); - - const saveUserSettingsResult = await request(app.getHttpServer()) - .post('/user/settings') - .send({ userSettings: settings }) - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - t.is(saveUserSettingsResult.status, 201); - - const getUserSettingsResult = await request(app.getHttpServer()) - .get('/user/settings') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const getUserSettingsRO = JSON.parse(getUserSettingsResult.text); - t.is(getUserSettingsResult.status, 200); - t.is(Object.hasOwn(getUserSettingsRO, 'userSettings'), true); - t.is(JSON.parse(getUserSettingsRO.userSettings).test, 'test'); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { token } = adminUserRegisterInfo; + + const settings = JSON.stringify({ test: 'test' }); + + const saveUserSettingsResult = await request(app.getHttpServer()) + .post('/user/settings') + .send({ userSettings: settings }) + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + t.is(saveUserSettingsResult.status, 201); + + const getUserSettingsResult = await request(app.getHttpServer()) + .get('/user/settings') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const getUserSettingsRO = JSON.parse(getUserSettingsResult.text); + t.is(getUserSettingsResult.status, 200); + t.is(Object.hasOwn(getUserSettingsRO, 'userSettings'), true); + t.is(JSON.parse(getUserSettingsRO.userSettings).test, 'test'); + t.pass(); }); currentTest = 'PUT user/test/connections/display/'; test.serial(`${currentTest} should toggle test connections display mode`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { token } = adminUserRegisterInfo; - - //get user connections (test connections should be included) - - const getUserConnectionsResult = await request(app.getHttpServer()) - .get('/connections') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const getUserConnectionsRO = JSON.parse(getUserConnectionsResult.text); - t.is(getUserConnectionsResult.status, 200); - t.is(Object.hasOwn(getUserConnectionsRO, 'connections'), true); - t.is(getUserConnectionsRO.connections.length, 4); - - const toggleTestConnectionsDisplayModeResult = await request(app.getHttpServer()) - .put('/user/test/connections/display/?displayMode=off') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const toggleTestConnectionsDisplayModeRO = JSON.parse(toggleTestConnectionsDisplayModeResult.text); - t.is(toggleTestConnectionsDisplayModeResult.status, 200); - t.truthy(toggleTestConnectionsDisplayModeRO.success); - - //get user connections (test connections shouldn't be included) - - const getUserConnectionsResultAfterToggleMode = await request(app.getHttpServer()) - .get('/connections') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const getUserConnectionsROAfterToggleMode = JSON.parse(getUserConnectionsResultAfterToggleMode.text); - t.is(getUserConnectionsResultAfterToggleMode.status, 200); - t.is(Object.hasOwn(getUserConnectionsROAfterToggleMode, 'connections'), true); - t.is(getUserConnectionsROAfterToggleMode.connections.length, 0); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { token } = adminUserRegisterInfo; + + //get user connections (test connections should be included) + + const getUserConnectionsResult = await request(app.getHttpServer()) + .get('/connections') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const getUserConnectionsRO = JSON.parse(getUserConnectionsResult.text); + t.is(getUserConnectionsResult.status, 200); + t.is(Object.hasOwn(getUserConnectionsRO, 'connections'), true); + t.is(getUserConnectionsRO.connections.length, 4); + + const toggleTestConnectionsDisplayModeResult = await request(app.getHttpServer()) + .put('/user/test/connections/display/?displayMode=off') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const toggleTestConnectionsDisplayModeRO = JSON.parse(toggleTestConnectionsDisplayModeResult.text); + t.is(toggleTestConnectionsDisplayModeResult.status, 200); + t.truthy(toggleTestConnectionsDisplayModeRO.success); + + //get user connections (test connections shouldn't be included) + + const getUserConnectionsResultAfterToggleMode = await request(app.getHttpServer()) + .get('/connections') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const getUserConnectionsROAfterToggleMode = JSON.parse(getUserConnectionsResultAfterToggleMode.text); + t.is(getUserConnectionsResultAfterToggleMode.status, 200); + t.is(Object.hasOwn(getUserConnectionsROAfterToggleMode, 'connections'), true); + t.is(getUserConnectionsROAfterToggleMode.connections.length, 0); + t.pass(); }); test.serial( - `${currentTest} should throw exception when user login with company id from custom domain (domain not added)`, - async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { email, password } = adminUserRegisterInfo; - - const foundCompanyInfos = await request(app.getHttpServer()) - .get(`/company/my/email/${email}`) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const foundCompanyInfosRO = JSON.parse(foundCompanyInfos.text); - - const loginBodyRequest = { - email, - password, - companyId: foundCompanyInfosRO[0].id, - }; - const testHostName = faker.internet.domainName(); - const loginUserResult = await request(app.getHttpServer()) - .post('/user/login/') - .send(loginBodyRequest) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json') - .set('Host', testHostName); - - t.is(loginUserResult.status, 400); - const loginUserRO = JSON.parse(loginUserResult.text); - t.is(loginUserRO.message, Messages.INVALID_REQUEST_DOMAIN); - t.pass(); - }, + `${currentTest} should throw exception when user login with company id from custom domain (domain not added)`, + async (t) => { + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { email, password } = adminUserRegisterInfo; + + const foundCompanyInfos = await request(app.getHttpServer()) + .get(`/company/my/email/${email}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const foundCompanyInfosRO = JSON.parse(foundCompanyInfos.text); + + const loginBodyRequest = { + email, + password, + companyId: foundCompanyInfosRO[0].id, + }; + const testHostName = faker.internet.domainName(); + const loginUserResult = await request(app.getHttpServer()) + .post('/user/login/') + .send(loginBodyRequest) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json') + .set('Host', testHostName); + + t.is(loginUserResult.status, 400); + const loginUserRO = JSON.parse(loginUserResult.text); + t.is(loginUserRO.message, Messages.INVALID_REQUEST_DOMAIN); + t.pass(); + }, ); test.skip(`${currentTest} should login user successfully with company id from custom domain (is added)`, async (t) => { - const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); - const { email, password, token } = adminUserRegisterInfo; - - const foundCompanyInfos = await request(app.getHttpServer()) - .get(`/company/my/email/${email}`) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const foundCompanyInfosRO = JSON.parse(foundCompanyInfos.text); - const companyId = foundCompanyInfosRO[0].id; - - const loginBodyRequest = { - email, - password, - companyId, - }; - - const customDomain = faker.internet.domainName(); - const requestDomainData = { - hostname: customDomain, - }; - - const registerDomainResponse = await sendRequestToSaasPart( - `custom-domain/register/${companyId}`, - 'POST', - requestDomainData, - token, - ); - t.is(registerDomainResponse.status, 201); - const registerDomainResponseRO = await registerDomainResponse.json(); - - t.is(registerDomainResponseRO.hostname, customDomain); - t.is(registerDomainResponseRO.companyId, companyId); - t.is(Object.hasOwn(registerDomainResponseRO, 'id'), true); - t.is(Object.hasOwn(registerDomainResponseRO, 'createdAt'), true); - t.is(Object.keys(registerDomainResponseRO).length, 5); - - delete loginBodyRequest.companyId; - const loginUserResult = await request(app.getHttpServer()) - .post('/user/login/') - .send(loginBodyRequest) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json') - .set('Host', customDomain); - - t.is(loginUserResult.status, 201); - t.pass(); + const adminUserRegisterInfo = await registerUserAndReturnUserInfo(app); + const { email, password, token } = adminUserRegisterInfo; + + const foundCompanyInfos = await request(app.getHttpServer()) + .get(`/company/my/email/${email}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const foundCompanyInfosRO = JSON.parse(foundCompanyInfos.text); + const companyId = foundCompanyInfosRO[0].id; + + const loginBodyRequest = { + email, + password, + companyId, + }; + + const customDomain = faker.internet.domainName(); + const requestDomainData = { + hostname: customDomain, + }; + + const registerDomainResponse = await sendRequestToSaasPart( + `custom-domain/register/${companyId}`, + 'POST', + requestDomainData, + token, + ); + t.is(registerDomainResponse.status, 201); + const registerDomainResponseRO = await registerDomainResponse.json(); + + t.is(registerDomainResponseRO.hostname, customDomain); + t.is(registerDomainResponseRO.companyId, companyId); + t.is(Object.hasOwn(registerDomainResponseRO, 'id'), true); + t.is(Object.hasOwn(registerDomainResponseRO, 'createdAt'), true); + t.is(Object.keys(registerDomainResponseRO).length, 5); + + delete loginBodyRequest.companyId; + const loginUserResult = await request(app.getHttpServer()) + .post('/user/login/') + .send(loginBodyRequest) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json') + .set('Host', customDomain); + + t.is(loginUserResult.status, 201); + t.pass(); }); currentTest = 'POST /user/demo/register'; test.serial(`${currentTest} should register demo user`, async (t) => { - const result = await fetch('http://rocketadmin-private-microservice:3001/saas/user/demo/register', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', - }, - }); - if (result.status > 201) { - console.info('result.body -> ', await result.json()); - } - const token = `${Constants.JWT_COOKIE_KEY_NAME}=${TestUtils.getJwtTokenFromResponse2(result)}`; - - //check test connections was created - const getUserConnectionsResult = await request(app.getHttpServer()) - .get('/connections') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const getUserConnectionsRO = JSON.parse(getUserConnectionsResult.text); - t.is(getUserConnectionsResult.status, 200); - t.is(Object.hasOwn(getUserConnectionsRO, 'connections'), true); - t.is(getUserConnectionsRO.connections.length, 4); - - //check user can add connection and use it - - const connectionToTestDB = getTestData(mockFactory).connectionToPostgres; - - const { testTableName, testTableColumnName, testEntitiesSeedsCount, testTableSecondColumnName } = - await createTestTable(connectionToTestDB); - - const createConnectionResponse = await request(app.getHttpServer()) - .post('/connection') - .send(connectionToTestDB) - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const createConnectionRO = JSON.parse(createConnectionResponse.text); - t.is(createConnectionResponse.status, 201); - - const getTableRowsResponse = await request(app.getHttpServer()) - .get(`/table/rows/${createConnectionRO.id}?tableName=${testTableName}&page=1&perPage=50`) - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - - const getTableRowsRO = JSON.parse(getTableRowsResponse.text); - t.is(getTableRowsResponse.status, 200); - - t.is(typeof getTableRowsRO, 'object'); - t.is(Object.hasOwn(getTableRowsRO, 'rows'), true); - t.is(Object.hasOwn(getTableRowsRO, 'primaryColumns'), true); - t.is(Object.hasOwn(getTableRowsRO, 'pagination'), true); - t.is(getTableRowsRO.rows.length, 42); - t.is(typeof getTableRowsRO.primaryColumns, 'object'); - t.is(Object.hasOwn(getTableRowsRO.primaryColumns[0], 'column_name'), true); - t.is(Object.hasOwn(getTableRowsRO.primaryColumns[0], 'data_type'), true); - t.is(getTableRowsRO.primaryColumns[0].column_name, 'id'); - t.is(getTableRowsRO.primaryColumns[0].data_type, 'integer'); - - //check that user has a company - - const getUserCompanyResult = await request(app.getHttpServer()) - .get('/company/my/full') - .set('Cookie', token) - .set('Content-Type', 'application/json') - .set('Accept', 'application/json'); - const getUserCompanyRO = JSON.parse(getUserCompanyResult.text); - t.is(getUserCompanyResult.status, 200); - - t.truthy(getUserCompanyRO); - t.is(typeof getUserCompanyRO, 'object'); - t.is(Object.hasOwn(getUserCompanyRO, 'id'), true); - t.is(typeof getUserCompanyRO.id, 'string'); - t.is(Object.hasOwn(getUserCompanyRO, 'name'), true); - t.is(typeof getUserCompanyRO.name, 'string'); - t.is(Object.hasOwn(getUserCompanyRO, 'subscriptionLevel'), true); - t.is(getUserCompanyRO.subscriptionLevel, 'TEAM_PLAN'); - t.is(Object.hasOwn(getUserCompanyRO, 'is_payment_method_added'), true); - t.is(getUserCompanyRO.is_payment_method_added, false); - t.is(Object.hasOwn(getUserCompanyRO, 'is2faEnabled'), true); - t.is(getUserCompanyRO.is2faEnabled, false); - t.is(Object.hasOwn(getUserCompanyRO, 'show_test_connections'), true); - t.is(getUserCompanyRO.show_test_connections, true); - t.is(Object.hasOwn(getUserCompanyRO, 'connections'), true); - t.true(Array.isArray(getUserCompanyRO.connections)); - t.is(getUserCompanyRO.connections.length, 5); - - for (const connection of getUserCompanyRO.connections) { - t.is(typeof connection.id, 'string'); - t.is(typeof connection.title, 'string'); - t.is(typeof connection.author, 'object'); - t.is(connection.author.role, 'ADMIN'); - t.true(Array.isArray(connection.groups)); - for (const group of connection.groups) { - t.is(typeof group.id, 'string'); - t.is(group.isMain, true); - t.is(typeof group.title, 'string'); - t.true(Array.isArray(group.users)); - for (const user of group.users) { - t.is(typeof user.id, 'string'); - t.is(user.role, 'ADMIN'); - t.is(typeof user.email, 'string'); - } - } - } + const result = await fetch('http://rocketadmin-private-microservice:3001/saas/user/demo/register', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + }); + if (result.status > 201) { + console.info('result.body -> ', await result.json()); + } + const token = `${Constants.JWT_COOKIE_KEY_NAME}=${TestUtils.getJwtTokenFromResponse2(result)}`; + + //check test connections was created + const getUserConnectionsResult = await request(app.getHttpServer()) + .get('/connections') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const getUserConnectionsRO = JSON.parse(getUserConnectionsResult.text); + t.is(getUserConnectionsResult.status, 200); + t.is(Object.hasOwn(getUserConnectionsRO, 'connections'), true); + t.is(getUserConnectionsRO.connections.length, 4); + + //check user can add connection and use it + + const connectionToTestDB = getTestData(mockFactory).connectionToPostgres; + + const { testTableName, testTableColumnName, testEntitiesSeedsCount, testTableSecondColumnName } = + await createTestTable(connectionToTestDB); + + const createConnectionResponse = await request(app.getHttpServer()) + .post('/connection') + .send(connectionToTestDB) + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const createConnectionRO = JSON.parse(createConnectionResponse.text); + t.is(createConnectionResponse.status, 201); + + const getTableRowsResponse = await request(app.getHttpServer()) + .get(`/table/rows/${createConnectionRO.id}?tableName=${testTableName}&page=1&perPage=50`) + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + + const getTableRowsRO = JSON.parse(getTableRowsResponse.text); + t.is(getTableRowsResponse.status, 200); + + t.is(typeof getTableRowsRO, 'object'); + t.is(Object.hasOwn(getTableRowsRO, 'rows'), true); + t.is(Object.hasOwn(getTableRowsRO, 'primaryColumns'), true); + t.is(Object.hasOwn(getTableRowsRO, 'pagination'), true); + t.is(getTableRowsRO.rows.length, 42); + t.is(typeof getTableRowsRO.primaryColumns, 'object'); + t.is(Object.hasOwn(getTableRowsRO.primaryColumns[0], 'column_name'), true); + t.is(Object.hasOwn(getTableRowsRO.primaryColumns[0], 'data_type'), true); + t.is(getTableRowsRO.primaryColumns[0].column_name, 'id'); + t.is(getTableRowsRO.primaryColumns[0].data_type, 'integer'); + + //check that user has a company + + const getUserCompanyResult = await request(app.getHttpServer()) + .get('/company/my/full') + .set('Cookie', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json'); + const getUserCompanyRO = JSON.parse(getUserCompanyResult.text); + t.is(getUserCompanyResult.status, 200); + + t.truthy(getUserCompanyRO); + t.is(typeof getUserCompanyRO, 'object'); + t.is(Object.hasOwn(getUserCompanyRO, 'id'), true); + t.is(typeof getUserCompanyRO.id, 'string'); + t.is(Object.hasOwn(getUserCompanyRO, 'name'), true); + t.is(typeof getUserCompanyRO.name, 'string'); + t.is(Object.hasOwn(getUserCompanyRO, 'subscriptionLevel'), true); + t.is(getUserCompanyRO.subscriptionLevel, 'TEAM_PLAN'); + t.is(Object.hasOwn(getUserCompanyRO, 'is_payment_method_added'), true); + t.is(getUserCompanyRO.is_payment_method_added, false); + t.is(Object.hasOwn(getUserCompanyRO, 'is2faEnabled'), true); + t.is(getUserCompanyRO.is2faEnabled, false); + t.is(Object.hasOwn(getUserCompanyRO, 'show_test_connections'), true); + t.is(getUserCompanyRO.show_test_connections, true); + t.is(Object.hasOwn(getUserCompanyRO, 'connections'), true); + t.true(Array.isArray(getUserCompanyRO.connections)); + t.is(getUserCompanyRO.connections.length, 5); + + for (const connection of getUserCompanyRO.connections) { + t.is(typeof connection.id, 'string'); + t.is(typeof connection.title, 'string'); + t.is(typeof connection.author, 'object'); + t.is(connection.author.role, 'ADMIN'); + t.true(Array.isArray(connection.groups)); + for (const group of connection.groups) { + t.is(typeof group.id, 'string'); + t.is(group.isMain, true); + t.is(typeof group.title, 'string'); + t.true(Array.isArray(group.users)); + for (const user of group.users) { + t.is(typeof user.id, 'string'); + t.is(user.role, 'ADMIN'); + t.is(typeof user.email, 'string'); + } + } + } }); diff --git a/frontend/CLAUDE.md b/frontend/CLAUDE.md index 86ae600ea..231c5164a 100644 --- a/frontend/CLAUDE.md +++ b/frontend/CLAUDE.md @@ -42,10 +42,11 @@ yarn install # Install dependencies ## 🏗 Architecture Overview ### Core Technologies -- **Angular 19** with standalone components architecture +- **Angular 20** with standalone components architecture - **TypeScript 5.6** targeting ES2022 -- **Angular Material 19** for UI components -- **RxJS 7.4** for reactive programming +- **Angular Signals** for reactive state management +- **Angular Material 19** for UI components +- **RxJS 7.4** for reactive programming (HTTP calls, complex streams) - **SCSS** with Material Design theming - **Jasmine/Karma** for testing @@ -66,21 +67,47 @@ export class ExampleComponent implements OnInit { } ``` -#### Service-Based State Management -No NgRx - uses BehaviorSubject pattern for state management: +#### Signal-Based State Management (Required for New Code) +All new code must use Angular signals for state management. Use `rxResource` for data fetching: ```typescript @Injectable({ providedIn: 'root' }) export class DataService { - private dataSubject = new BehaviorSubject(''); - public cast = this.dataSubject.asObservable(); - - updateData(newData: any) { - this.dataSubject.next(newData); + private _http = inject(HttpClient); + + // Reactive parameter for data fetching + private _activeId = signal(null); + + // Use rxResource for reactive data fetching + private _dataResource = rxResource({ + params: () => this._activeId(), + stream: ({ params: id }) => { + if (!id) return EMPTY; + return this._http.get(`/api/data/${id}`); + }, + }); + + // Expose as readonly signals + public readonly data = computed(() => this._dataResource.value() ?? []); + public readonly loading = computed(() => this._dataResource.isLoading()); + + setActiveId(id: string): void { + this._activeId.set(id); + } + + refresh(): void { + this._dataResource.reload(); } } ``` +**Legacy pattern** (BehaviorSubject - avoid in new code): +```typescript +// Old pattern - do not use for new code +private dataSubject = new BehaviorSubject(''); +public cast = this.dataSubject.asObservable(); +``` + #### Multi-Environment Support The app supports multiple deployment environments: - `environment.ts` - Development @@ -166,7 +193,7 @@ import { BaseRowFieldComponent } from '../base-row-field/base-row-field.componen import { DataService } from 'src/app/services/data.service'; ``` -### Component Structure +### Component Structure (Signal-Based) ```typescript @Component({ selector: 'app-widget-name', @@ -175,27 +202,41 @@ import { DataService } from 'src/app/services/data.service'; imports: [CommonModule, MatModule, ...], // All required imports }) export class WidgetNameComponent implements OnInit { - // Input/Output properties first - @Input() inputProperty: string; - @Output() outputEvent = new EventEmitter(); - - // Public properties - public publicProperty: string; - - // Private properties - private _privateProperty: string; - + // Dependency injection + private _dataService = inject(DataService); + + // Signals for component state (required for new code) + protected loading = signal(false); + protected items = signal([]); + protected searchQuery = signal(''); + + // Computed signals for derived state + protected filteredItems = computed(() => { + const items = this.items(); + const query = this.searchQuery().toLowerCase(); + return query ? items.filter(i => i.name.toLowerCase().includes(query)) : items; + }); + + // Effects for side effects + constructor() { + effect(() => { + const query = this.searchQuery(); + // React to signal changes + }); + } + // Lifecycle hooks ngOnInit(): void { // Initialization logic } - + // Public methods - public handleClick(): void { + handleClick(): void { + this.loading.set(true); // Event handling } - - // Private methods + + // Private methods at the end private _helperMethod(): void { // Internal logic } @@ -211,23 +252,47 @@ export class WidgetNameComponent implements OnInit { ### Test Structure ```typescript +// Define testable type for accessing protected signals (avoid `as any`) +type ComponentNameTestable = ComponentName & { + loading: Signal; + items: WritableSignal; + searchQuery: WritableSignal; +}; + describe('ComponentName', () => { let component: ComponentName; let fixture: ComponentFixture; - + let mockDataService: Partial; + beforeEach(async () => { + // Use Partial instead of `any` for mocks + mockDataService = { + data: signal([]).asReadonly(), + loading: signal(false).asReadonly(), + setActiveId: vi.fn(), + }; + await TestBed.configureTestingModule({ imports: [ComponentName, MaterialModules, ...], - providers: [provideHttpClient(), MockServices, ...] + providers: [ + provideHttpClient(), + { provide: DataService, useValue: mockDataService }, + ] }).compileComponents(); - + fixture = TestBed.createComponent(ComponentName); component = fixture.componentInstance; }); - + it('should create', () => { expect(component).toBeTruthy(); }); + + it('should access protected signals with proper typing', () => { + const testable = component as ComponentNameTestable; + testable.searchQuery.set('test'); + expect(testable.loading()).toBe(false); + }); }); ``` @@ -288,6 +353,15 @@ Custom launcher `ChromeHeadlessCustom` is configured for CI with flags `--no-san ## 🚨 Important Notes +### Signals Requirement +**All new code must use Angular signals** for state management: +- Use `signal()` for component state instead of plain properties +- Use `computed()` for derived state +- Use `effect()` for side effects +- Use `rxResource()` in services for data fetching +- Avoid BehaviorSubject in new code +- Never use `as any` in tests - use `Partial` and testable type aliases + ### Migration Recommendations - **TSLint → ESLint**: Current linting uses deprecated TSLint - **Material Design 3**: Consider upgrading from M2 to M3 APIs diff --git a/frontend/package.json b/frontend/package.json index 8c4996130..de875bdb3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -38,6 +38,7 @@ "amplitude-js": "^8.21.9", "angular-password-strength-meter": "npm:@eresearchqut/angular-password-strength-meter@^13.0.7", "angulartics2": "^14.1.0", + "chart.js": "^4.5.1", "color-string": "^2.0.1", "convert": "^5.12.0", "date-fns": "^4.1.0", @@ -50,6 +51,7 @@ "mermaid": "^11.12.1", "monaco-editor": "0.55.1", "ng-dynamic-component": "^10.8.0", + "ng2-charts": "^8.0.0", "ngx-cookie-service": "^19.0.0", "ngx-markdown": "^19.1.1", "ngx-stripe": "^19.0.0", diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index 882bf4b46..01a0f249d 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -1,46 +1,219 @@ +import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; - import { AuthGuard } from './auth.guard'; -import { NgModule } from '@angular/core'; const routes: Routes = [ - {path: '', redirectTo: '/connections-list', pathMatch: 'full'}, - {path: 'loader', loadComponent: () => import('./components/page-loader/page-loader.component').then(m => m.PageLoaderComponent)}, - {path: 'registration', loadChildren: () => import('./routes/registration.routes').then(m => m.REGISTRATION_ROUTES)}, - {path: 'login', loadComponent: () => import('./components/login/login.component').then(m => m.LoginComponent), title: 'Login | Rocketadmin'}, - {path: 'forget-password', loadComponent: () => import('./components/password-request/password-request.component').then(m => m.PasswordRequestComponent), title: 'Request password | Rocketadmin'}, - {path: 'external/user/password/reset/verify/:verification-token', loadChildren: () => import('./routes/password-reset.routes').then(m => m.PASSWORD_RESET_ROUTES)}, - {path: 'external/user/email/verify/:verification-token', loadComponent: () => import('./components/email-verification/email-verification.component').then(m => m.EmailVerificationComponent), title: 'Email verification | Rocketadmin'}, - {path: 'external/user/email/change/verify/:change-token', loadComponent: () => import('./components/email-change/email-change.component').then(m => m.EmailChangeComponent), title: 'Email updating | Rocketadmin'}, - {path: 'deleted', loadComponent: () => import('./components/user-deleted-success/user-deleted-success.component').then(m => m.UserDeletedSuccessComponent), title: 'User deleted | Rocketadmin'}, - {path: 'connect-db', loadComponent: () => import('./components/connect-db/connect-db.component').then(m => m.ConnectDBComponent), canActivate: [AuthGuard]}, - {path: 'connections-list', loadComponent: () => import('./components/connections-list/connections-list.component').then(m => m.ConnectionsListComponent), canActivate: [AuthGuard]}, - {path: 'user-settings', loadComponent: () => import('./components/user-settings/user-settings.component').then(m => m.UserSettingsComponent), canActivate: [AuthGuard]}, - // company routes have to be in this specific order - {path: 'company/:company-id/verify/:verification-token', pathMatch: 'full', loadChildren: () => import('./routes/company-invitation.routes').then(m => m.COMPANY_INVITATION_ROUTES)}, - {path: 'company', pathMatch: 'full', loadComponent: () => import('./components/company/company.component').then(m => m.CompanyComponent), canActivate: [AuthGuard]}, - {path: 'secrets', pathMatch: 'full', loadComponent: () => import('./components/secrets/secrets.component').then(m => m.SecretsComponent), canActivate: [AuthGuard], title: 'Secrets | Rocketadmin'}, - {path: 'sso/:company-id', pathMatch: 'full', loadComponent: () => import('./components/sso/sso.component').then(m => m.SsoComponent), canActivate: [AuthGuard]}, - {path: 'change-password', loadChildren: () => import('./routes/password-change.routes').then(m => m.PASSWORD_CHANGE_ROUTES)}, - {path: 'upgrade', loadComponent: () => import('./components/upgrade/upgrade.component').then(m => m.UpgradeComponent), canActivate: [AuthGuard], title: 'Upgrade | Rocketadmin'}, - {path: 'upgrade/payment', loadComponent: () => import('./components/payment-form/payment-form.component').then(m => m.PaymentFormComponent), canActivate: [AuthGuard], title: 'Payment | Rocketadmin'}, - {path: 'subscription/success', loadComponent: () => import('./components/upgrade-success/upgrade-success.component').then(m => m.UpgradeSuccessComponent), canActivate: [AuthGuard], title: 'Upgraded successfully | Rocketadmin'}, - {path: 'edit-db/:connection-id', loadComponent: () => import('./components/connect-db/connect-db.component').then(m => m.ConnectDBComponent), canActivate: [AuthGuard]}, - {path: 'connection-settings/:connection-id', loadComponent: () => import('./components/connection-settings/connection-settings.component').then(m => m.ConnectionSettingsComponent), canActivate: [AuthGuard]}, - {path: 'dashboard/:connection-id', loadComponent: () => import('./components/dashboard/dashboard.component').then(m => m.DashboardComponent), canActivate: [AuthGuard]}, - {path: 'audit/:connection-id', loadComponent: () => import('./components/audit/audit.component').then(m => m.AuditComponent), canActivate: [AuthGuard]}, - {path: 'dashboard/:connection-id/:table-name', pathMatch: 'full', loadComponent: () => import('./components/dashboard/dashboard.component').then(m => m.DashboardComponent), canActivate: [AuthGuard]}, - {path: 'dashboard/:connection-id/:table-name/entry', pathMatch: 'full', loadComponent: () => import('./components/db-table-row-edit/db-table-row-edit.component').then(m => m.DbTableRowEditComponent), canActivate: [AuthGuard]}, - {path: 'dashboard/:connection-id/:table-name/widgets', pathMatch: 'full', loadComponent: () => import('./components/dashboard/db-table-view/db-table-widgets/db-table-widgets.component').then(m => m.DbTableWidgetsComponent), canActivate: [AuthGuard]}, - {path: 'dashboard/:connection-id/:table-name/settings', pathMatch: 'full', loadComponent: () => import('./components/dashboard/db-table-view/db-table-settings/db-table-settings.component').then(m => m.DbTableSettingsComponent), canActivate: [AuthGuard]}, - {path: 'dashboard/:connection-id/:table-name/actions', pathMatch: 'full', loadComponent: () => import('./components/dashboard/db-table-view/db-table-actions/db-table-actions.component').then(m => m.DbTableActionsComponent), canActivate: [AuthGuard]}, - {path: 'permissions/:connection-id', loadComponent: () => import('./components/users/users.component').then(m => m.UsersComponent), canActivate: [AuthGuard]}, - {path: 'zapier', loadComponent: () => import('./components/zapier/zapier.component').then(m => m.ZapierComponent), canActivate: [AuthGuard]}, - {path: '**', loadComponent: () => import('./components/page-not-found/page-not-found.component').then(m => m.PageNotFoundComponent)}, + { path: '', redirectTo: '/connections-list', pathMatch: 'full' }, + { + path: 'loader', + loadComponent: () => import('./components/page-loader/page-loader.component').then((m) => m.PageLoaderComponent), + }, + { + path: 'registration', + loadChildren: () => import('./routes/registration.routes').then((m) => m.REGISTRATION_ROUTES), + }, + { + path: 'login', + loadComponent: () => import('./components/login/login.component').then((m) => m.LoginComponent), + title: 'Login | Rocketadmin', + }, + { + path: 'forget-password', + loadComponent: () => + import('./components/password-request/password-request.component').then((m) => m.PasswordRequestComponent), + title: 'Request password | Rocketadmin', + }, + { + path: 'external/user/password/reset/verify/:verification-token', + loadChildren: () => import('./routes/password-reset.routes').then((m) => m.PASSWORD_RESET_ROUTES), + }, + { + path: 'external/user/email/verify/:verification-token', + loadComponent: () => + import('./components/email-verification/email-verification.component').then((m) => m.EmailVerificationComponent), + title: 'Email verification | Rocketadmin', + }, + { + path: 'external/user/email/change/verify/:change-token', + loadComponent: () => import('./components/email-change/email-change.component').then((m) => m.EmailChangeComponent), + title: 'Email updating | Rocketadmin', + }, + { + path: 'deleted', + loadComponent: () => + import('./components/user-deleted-success/user-deleted-success.component').then( + (m) => m.UserDeletedSuccessComponent, + ), + title: 'User deleted | Rocketadmin', + }, + { + path: 'connect-db', + loadComponent: () => import('./components/connect-db/connect-db.component').then((m) => m.ConnectDBComponent), + canActivate: [AuthGuard], + }, + { + path: 'connections-list', + loadComponent: () => + import('./components/connections-list/connections-list.component').then((m) => m.ConnectionsListComponent), + canActivate: [AuthGuard], + }, + { + path: 'user-settings', + loadComponent: () => + import('./components/user-settings/user-settings.component').then((m) => m.UserSettingsComponent), + canActivate: [AuthGuard], + }, + // company routes have to be in this specific order + { + path: 'company/:company-id/verify/:verification-token', + pathMatch: 'full', + loadChildren: () => import('./routes/company-invitation.routes').then((m) => m.COMPANY_INVITATION_ROUTES), + }, + { + path: 'company', + pathMatch: 'full', + loadComponent: () => import('./components/company/company.component').then((m) => m.CompanyComponent), + canActivate: [AuthGuard], + }, + { + path: 'secrets', + pathMatch: 'full', + loadComponent: () => import('./components/secrets/secrets.component').then((m) => m.SecretsComponent), + canActivate: [AuthGuard], + title: 'Secrets | Rocketadmin', + }, + { + path: 'sso/:company-id', + pathMatch: 'full', + loadComponent: () => import('./components/sso/sso.component').then((m) => m.SsoComponent), + canActivate: [AuthGuard], + }, + { + path: 'change-password', + loadChildren: () => import('./routes/password-change.routes').then((m) => m.PASSWORD_CHANGE_ROUTES), + }, + { + path: 'upgrade', + loadComponent: () => import('./components/upgrade/upgrade.component').then((m) => m.UpgradeComponent), + canActivate: [AuthGuard], + title: 'Upgrade | Rocketadmin', + }, + { + path: 'upgrade/payment', + loadComponent: () => import('./components/payment-form/payment-form.component').then((m) => m.PaymentFormComponent), + canActivate: [AuthGuard], + title: 'Payment | Rocketadmin', + }, + { + path: 'subscription/success', + loadComponent: () => + import('./components/upgrade-success/upgrade-success.component').then((m) => m.UpgradeSuccessComponent), + canActivate: [AuthGuard], + title: 'Upgraded successfully | Rocketadmin', + }, + { + path: 'edit-db/:connection-id', + loadComponent: () => import('./components/connect-db/connect-db.component').then((m) => m.ConnectDBComponent), + canActivate: [AuthGuard], + }, + { + path: 'connection-settings/:connection-id', + loadComponent: () => + import('./components/connection-settings/connection-settings.component').then( + (m) => m.ConnectionSettingsComponent, + ), + canActivate: [AuthGuard], + }, + { + path: 'dashboard/:connection-id', + loadComponent: () => import('./components/dashboard/dashboard.component').then((m) => m.DashboardComponent), + canActivate: [AuthGuard], + }, + { + path: 'audit/:connection-id', + loadComponent: () => import('./components/audit/audit.component').then((m) => m.AuditComponent), + canActivate: [AuthGuard], + }, + { + path: 'dashboard/:connection-id/:table-name', + pathMatch: 'full', + loadComponent: () => import('./components/dashboard/dashboard.component').then((m) => m.DashboardComponent), + canActivate: [AuthGuard], + }, + { + path: 'dashboard/:connection-id/:table-name/entry', + pathMatch: 'full', + loadComponent: () => + import('./components/db-table-row-edit/db-table-row-edit.component').then((m) => m.DbTableRowEditComponent), + canActivate: [AuthGuard], + }, + { + path: 'dashboard/:connection-id/:table-name/widgets', + pathMatch: 'full', + loadComponent: () => + import('./components/dashboard/db-table-view/db-table-widgets/db-table-widgets.component').then( + (m) => m.DbTableWidgetsComponent, + ), + canActivate: [AuthGuard], + }, + { + path: 'dashboard/:connection-id/:table-name/settings', + pathMatch: 'full', + loadComponent: () => + import('./components/dashboard/db-table-view/db-table-settings/db-table-settings.component').then( + (m) => m.DbTableSettingsComponent, + ), + canActivate: [AuthGuard], + }, + { + path: 'dashboard/:connection-id/:table-name/actions', + pathMatch: 'full', + loadComponent: () => + import('./components/dashboard/db-table-view/db-table-actions/db-table-actions.component').then( + (m) => m.DbTableActionsComponent, + ), + canActivate: [AuthGuard], + }, + { + path: 'permissions/:connection-id', + loadComponent: () => import('./components/users/users.component').then((m) => m.UsersComponent), + canActivate: [AuthGuard], + }, + { + path: 'zapier', + loadComponent: () => import('./components/zapier/zapier.component').then((m) => m.ZapierComponent), + canActivate: [AuthGuard], + }, + { + path: 'charts/:connection-id', + loadComponent: () => + import('./components/charts/charts-list/charts-list.component').then((m) => m.ChartsListComponent), + canActivate: [AuthGuard], + title: 'Saved Queries | Rocketadmin', + }, + { + path: 'charts/:connection-id/new', + loadComponent: () => + import('./components/charts/chart-edit/chart-edit.component').then((m) => m.ChartEditComponent), + canActivate: [AuthGuard], + title: 'Create Query | Rocketadmin', + }, + { + path: 'charts/:connection-id/:query-id', + loadComponent: () => + import('./components/charts/chart-edit/chart-edit.component').then((m) => m.ChartEditComponent), + canActivate: [AuthGuard], + title: 'Edit Query | Rocketadmin', + }, + { + path: '**', + loadComponent: () => + import('./components/page-not-found/page-not-found.component').then((m) => m.PageNotFoundComponent), + }, ]; @NgModule({ - imports: [RouterModule.forRoot(routes)], - exports: [RouterModule] + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule], }) -export class AppRoutingModule { } +export class AppRoutingModule {} diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts index f5b9053a4..a06cfc14c 100644 --- a/frontend/src/app/app.component.ts +++ b/frontend/src/app/app.component.ts @@ -194,6 +194,9 @@ export class AppComponent { permissions: { caption: 'Permissions', }, + charts: { + caption: 'Charts', + }, 'connection-settings': { caption: 'Connection settings', }, diff --git a/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.css b/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.css new file mode 100644 index 000000000..2528b138d --- /dev/null +++ b/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.css @@ -0,0 +1,46 @@ +.warning-container { + display: flex; + gap: 16px; + padding: 16px; + background-color: #fff3e0; + border-radius: 8px; +} + +@media (prefers-color-scheme: dark) { + .warning-container { + background-color: rgba(255, 152, 0, 0.15); + } +} + +.warning-icon { + font-size: 32px; + width: 32px; + height: 32px; + color: #ef6c00; + flex-shrink: 0; +} + +@media (prefers-color-scheme: dark) { + .warning-icon { + color: #ffb74d; + } +} + +.warning-content p { + margin: 0; +} + +.warning-content p:first-child { + margin-bottom: 8px; +} + +.warning-details { + font-size: 14px; + color: rgba(0, 0, 0, 0.54); +} + +@media (prefers-color-scheme: dark) { + .warning-details { + color: rgba(255, 255, 255, 0.54); + } +} diff --git a/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.html b/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.html new file mode 100644 index 000000000..6c6f47234 --- /dev/null +++ b/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.html @@ -0,0 +1,23 @@ +

Delete Saved Query

+ + +
+ warning +
+

Are you sure you want to delete the query {{data.query.name}}?

+

+ This action cannot be undone. The query and its configuration will be permanently removed. +

+
+
+
+ + + + + diff --git a/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.spec.ts b/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.spec.ts new file mode 100644 index 000000000..01ac2695f --- /dev/null +++ b/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.spec.ts @@ -0,0 +1,118 @@ +import { provideHttpClient } from '@angular/common/http'; +import { provideHttpClientTesting } from '@angular/common/http/testing'; +import { WritableSignal } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { Angulartics2Module } from 'angulartics2'; +import { of, throwError } from 'rxjs'; +import { SavedQuery } from 'src/app/models/saved-query'; +import { SavedQueriesService } from 'src/app/services/saved-queries.service'; +import { ChartDeleteDialogComponent } from './chart-delete-dialog.component'; + +type ChartDeleteDialogComponentTestable = ChartDeleteDialogComponent & { + submitting: WritableSignal; +}; + +describe('ChartDeleteDialogComponent', () => { + let component: ChartDeleteDialogComponent; + let fixture: ComponentFixture; + let mockSavedQueriesService: Partial; + let mockDialogRef: Partial>; + + const mockSavedQuery: SavedQuery = { + id: '1', + name: 'Test Query', + description: 'Test description', + query_text: 'SELECT * FROM users', + connection_id: 'conn-1', + created_at: '2024-01-01', + updated_at: '2024-01-01', + }; + + beforeEach(async () => { + mockSavedQueriesService = { + deleteSavedQuery: vi.fn().mockReturnValue(of(mockSavedQuery)), + }; + + mockDialogRef = { + close: vi.fn(), + }; + + await TestBed.configureTestingModule({ + imports: [ + ChartDeleteDialogComponent, + BrowserAnimationsModule, + MatSnackBarModule, + MatDialogModule, + Angulartics2Module.forRoot(), + ], + providers: [ + provideHttpClient(), + provideHttpClientTesting(), + { provide: SavedQueriesService, useValue: mockSavedQueriesService }, + { provide: MatDialogRef, useValue: mockDialogRef }, + { + provide: MAT_DIALOG_DATA, + useValue: { query: mockSavedQuery, connectionId: 'conn-1' }, + }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(ChartDeleteDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should have submitting signal initialized to false', () => { + const testable = component as ChartDeleteDialogComponentTestable; + expect(testable.submitting()).toBe(false); + }); + + describe('onDelete', () => { + it('should call deleteSavedQuery service method', () => { + component.onDelete(); + expect(mockSavedQueriesService.deleteSavedQuery).toHaveBeenCalledWith('conn-1', '1'); + }); + + it('should set submitting to true during delete', () => { + component.onDelete(); + // The deleteSavedQuery returns synchronously in the mock, so submitting would be false after + // In real usage, submitting would be true while the request is in flight + expect(mockSavedQueriesService.deleteSavedQuery).toHaveBeenCalled(); + }); + + it('should close dialog with true on success', () => { + component.onDelete(); + expect(mockDialogRef.close).toHaveBeenCalledWith(true); + }); + + it('should set submitting to false after successful delete', () => { + const testable = component as ChartDeleteDialogComponentTestable; + component.onDelete(); + expect(testable.submitting()).toBe(false); + }); + + it('should set submitting to false on error', () => { + const testable = component as ChartDeleteDialogComponentTestable; + vi.mocked(mockSavedQueriesService.deleteSavedQuery!).mockReturnValue( + throwError(() => new Error('Delete failed')), + ); + component.onDelete(); + expect(testable.submitting()).toBe(false); + }); + + it('should not close dialog on error', () => { + vi.mocked(mockSavedQueriesService.deleteSavedQuery!).mockReturnValue( + throwError(() => new Error('Delete failed')), + ); + component.onDelete(); + expect(mockDialogRef.close).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.ts b/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.ts new file mode 100644 index 000000000..40f2fdc51 --- /dev/null +++ b/frontend/src/app/components/charts/chart-delete-dialog/chart-delete-dialog.component.ts @@ -0,0 +1,41 @@ +import { CommonModule } from '@angular/common'; +import { Component, Inject, signal } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; +import { MatIconModule } from '@angular/material/icon'; +import { Angulartics2 } from 'angulartics2'; +import { SavedQuery } from 'src/app/models/saved-query'; +import { SavedQueriesService } from 'src/app/services/saved-queries.service'; + +@Component({ + selector: 'app-chart-delete-dialog', + templateUrl: './chart-delete-dialog.component.html', + styleUrls: ['./chart-delete-dialog.component.css'], + imports: [CommonModule, MatDialogModule, MatButtonModule, MatIconModule], +}) +export class ChartDeleteDialogComponent { + protected submitting = signal(false); + + constructor( + @Inject(MAT_DIALOG_DATA) public data: { query: SavedQuery; connectionId: string }, + private dialogRef: MatDialogRef, + private _savedQueries: SavedQueriesService, + private angulartics2: Angulartics2, + ) {} + + onDelete(): void { + this.submitting.set(true); + this._savedQueries.deleteSavedQuery(this.data.connectionId, this.data.query.id).subscribe({ + next: () => { + this.angulartics2.eventTrack.next({ + action: 'Charts: saved query deleted successfully', + }); + this.submitting.set(false); + this.dialogRef.close(true); + }, + error: () => { + this.submitting.set(false); + }, + }); + } +} diff --git a/frontend/src/app/components/charts/chart-edit/chart-edit.component.css b/frontend/src/app/components/charts/chart-edit/chart-edit.component.css new file mode 100644 index 000000000..542475ae6 --- /dev/null +++ b/frontend/src/app/components/charts/chart-edit/chart-edit.component.css @@ -0,0 +1,219 @@ +.chart-edit-page { + margin: 2em auto; + padding: 0 clamp(100px, 10vw, 200px); + max-width: 1400px; +} + +@media (width <= 900px) { + .chart-edit-page { + padding: 0 16px; + } +} + +.chart-edit-header { + display: flex; + align-items: center; + gap: 16px; + margin-bottom: 24px; +} + +.chart-edit-header h1 { + margin: 0; +} + +.loading-container { + display: flex; + justify-content: center; + padding: 64px; +} + +.chart-edit-content { + display: flex; + flex-direction: column; + gap: 24px; +} + +.query-details { + display: flex; + gap: 16px; +} + +@media (width <= 600px) { + .query-details { + flex-direction: column; + } +} + +.name-field { + flex: 1; + max-width: 300px; +} + +@media (width <= 600px) { + .name-field { + max-width: 100%; + } +} + +.description-field { + flex: 2; +} + +.editor-preview-container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 24px; +} + +@media (width <= 900px) { + .editor-preview-container { + grid-template-columns: 1fr; + } +} + +.editor-section, +.preview-section { + display: flex; + flex-direction: column; + gap: 16px; +} + +.section-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; +} + +.section-header h3 { + margin: 0; + font-size: 16px; + font-weight: 500; +} + +.execution-time { + font-size: 12px; + color: rgba(0, 0, 0, 0.54); +} + +@media (prefers-color-scheme: dark) { + .execution-time { + color: rgba(255, 255, 255, 0.54); + } +} + +.code-editor-box { + height: 300px; + border: 1px solid rgba(0, 0, 0, 0.12); + border-radius: 4px; + overflow: hidden; +} + +@media (prefers-color-scheme: dark) { + .code-editor-box { + border-color: rgba(255, 255, 255, 0.12); + } +} + +.code-editor-box ngs-code-editor { + height: 100%; +} + +.chart-config { + display: flex; + gap: 16px; + flex-wrap: wrap; +} + +.chart-config-field { + flex: 1; + min-width: 150px; +} + +.chart-container { + min-height: 250px; + padding: 16px; + background-color: rgba(0, 0, 0, 0.02); + border-radius: 4px; +} + +@media (prefers-color-scheme: dark) { + .chart-container { + background-color: rgba(255, 255, 255, 0.05); + } +} + +.no-chart-data { + display: flex; + align-items: center; + justify-content: center; + min-height: 200px; + color: rgba(0, 0, 0, 0.54); + text-align: center; +} + +@media (prefers-color-scheme: dark) { + .no-chart-data { + color: rgba(255, 255, 255, 0.54); + } +} + +.results-section { + display: flex; + flex-direction: column; + gap: 16px; +} + +.results-table-container { + max-height: 300px; + overflow: auto; + border-radius: 4px; +} + +.results-table { + width: 100%; +} + +.results-table th { + font-weight: 500; +} + +.no-results { + display: flex; + align-items: center; + gap: 8px; + padding: 24px; + color: rgba(0, 0, 0, 0.54); + background-color: rgba(0, 0, 0, 0.02); + border-radius: 4px; +} + +@media (prefers-color-scheme: dark) { + .no-results { + color: rgba(255, 255, 255, 0.54); + background-color: rgba(255, 255, 255, 0.05); + } +} + +.no-results mat-icon { + color: #1976d2; +} + +.actions { + display: flex; + justify-content: flex-end; + gap: 16px; + padding-top: 16px; + border-top: 1px solid rgba(0, 0, 0, 0.12); +} + +@media (prefers-color-scheme: dark) { + .actions { + border-top-color: rgba(255, 255, 255, 0.12); + } +} + +.actions button mat-spinner { + display: inline-block; + margin-right: 8px; +} diff --git a/frontend/src/app/components/charts/chart-edit/chart-edit.component.html b/frontend/src/app/components/charts/chart-edit/chart-edit.component.html new file mode 100644 index 000000000..42358bdc6 --- /dev/null +++ b/frontend/src/app/components/charts/chart-edit/chart-edit.component.html @@ -0,0 +1,147 @@ + + +
+
+ +

{{ isEditMode() ? 'Edit Saved Query' : 'Create Saved Query' }}

+
+ +
+ +
+ +
+
+ + Query Name + + + + + Description (optional) + + +
+ +
+
+
+

SQL Query

+ +
+
+ + +
+
+ +
+
+

Chart Preview

+ + Executed in {{ executionTime() }}ms + +
+ +
+ + Chart Type + + + {{ type.label }} + + + + + + Label Column + + + {{ col }} + + + + + + Value Column + + + {{ col }} + + + +
+ +
+ + +
+ +
+

Select label and value columns to display the chart

+
+
+
+ +
+
+

Query Results ({{ testResults().length }} rows)

+
+
+ + + + + + + + +
{{ column }}{{ row[column] }}
+
+
+ +
+ info +

Query executed successfully but returned no results.

+
+ +
+ + +
+
+
diff --git a/frontend/src/app/components/charts/chart-edit/chart-edit.component.spec.ts b/frontend/src/app/components/charts/chart-edit/chart-edit.component.spec.ts new file mode 100644 index 000000000..58df8413b --- /dev/null +++ b/frontend/src/app/components/charts/chart-edit/chart-edit.component.spec.ts @@ -0,0 +1,281 @@ +import { provideHttpClient } from '@angular/common/http'; +import { provideHttpClientTesting } from '@angular/common/http/testing'; +import { NO_ERRORS_SCHEMA, Signal, WritableSignal } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { ActivatedRoute, Router } from '@angular/router'; +import { RouterTestingModule } from '@angular/router/testing'; +import { CodeEditorModule } from '@ngstack/code-editor'; +import { Angulartics2Module } from 'angulartics2'; +import { of } from 'rxjs'; +import { ChartType, SavedQuery } from 'src/app/models/saved-query'; +import { ConnectionsService } from 'src/app/services/connections.service'; +import { SavedQueriesService } from 'src/app/services/saved-queries.service'; +import { UiSettingsService } from 'src/app/services/ui-settings.service'; +import { MockCodeEditorComponent } from 'src/app/testing/code-editor.mock'; +import { ChartEditComponent } from './chart-edit.component'; + +type ChartEditComponentTestable = ChartEditComponent & { + isEditMode: WritableSignal; + queryName: WritableSignal; + queryText: WritableSignal; + queryDescription: WritableSignal; + saving: WritableSignal; + testing: WritableSignal; + testResults: WritableSignal[]>; + resultColumns: WritableSignal; + executionTime: WritableSignal; + labelColumn: WritableSignal; + valueColumn: WritableSignal; + chartType: WritableSignal; + canSave: Signal; + canTest: Signal; + hasChartData: Signal; +}; + +describe('ChartEditComponent', () => { + let component: ChartEditComponent; + let fixture: ComponentFixture; + let mockSavedQueriesService: Partial; + let mockConnectionsService: Partial; + let mockUiSettingsService: Partial; + let router: Router; + + const mockSavedQuery: SavedQuery = { + id: '1', + name: 'Test Query', + description: 'Test description', + query_text: 'SELECT * FROM users', + connection_id: 'conn-1', + created_at: '2024-01-01', + updated_at: '2024-01-01', + }; + + beforeEach(async () => { + mockSavedQueriesService = { + fetchSavedQuery: vi.fn().mockReturnValue(of(mockSavedQuery)), + createSavedQuery: vi.fn().mockReturnValue(of(mockSavedQuery)), + updateSavedQuery: vi.fn().mockReturnValue(of(mockSavedQuery)), + testQuery: vi.fn().mockReturnValue( + of({ + data: [{ name: 'John', count: 10 }], + execution_time_ms: 50, + }), + ), + }; + + mockConnectionsService = { + getCurrentConnectionTitle: vi.fn().mockReturnValue(of('Test Connection')), + }; + + mockUiSettingsService = { + editorTheme: 'vs-dark', + }; + + await TestBed.configureTestingModule({ + imports: [ + ChartEditComponent, + BrowserAnimationsModule, + MatSnackBarModule, + RouterTestingModule, + Angulartics2Module.forRoot(), + ], + providers: [ + provideHttpClient(), + provideHttpClientTesting(), + { provide: SavedQueriesService, useValue: mockSavedQueriesService }, + { provide: ConnectionsService, useValue: mockConnectionsService }, + { provide: UiSettingsService, useValue: mockUiSettingsService }, + { + provide: ActivatedRoute, + useValue: { + snapshot: { + paramMap: { + get: (key: string) => { + if (key === 'connection-id') return 'conn-1'; + if (key === 'query-id') return null; + return null; + }, + }, + }, + }, + }, + ], + }) + .overrideComponent(ChartEditComponent, { + remove: { imports: [CodeEditorModule] }, + add: { imports: [MockCodeEditorComponent], schemas: [NO_ERRORS_SCHEMA] }, + }) + .compileComponents(); + + router = TestBed.inject(Router); + vi.spyOn(router, 'navigate'); + + fixture = TestBed.createComponent(ChartEditComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should initialize in create mode when no query-id', () => { + const testable = component as ChartEditComponentTestable; + expect(testable.isEditMode()).toBe(false); + }); + + it('should set page title on init', () => { + expect(mockConnectionsService.getCurrentConnectionTitle).toHaveBeenCalled(); + }); + + it('should have correct default chart type', () => { + const testable = component as ChartEditComponentTestable; + expect(testable.chartType()).toBe('bar'); + }); + + describe('canSave computed', () => { + it('should return false when name is empty', () => { + const testable = component as ChartEditComponentTestable; + testable.queryName.set(''); + testable.queryText.set('SELECT 1'); + expect(testable.canSave()).toBe(false); + }); + + it('should return false when query is empty', () => { + const testable = component as ChartEditComponentTestable; + testable.queryName.set('Test'); + testable.queryText.set(''); + expect(testable.canSave()).toBe(false); + }); + + it('should return true when name and query are provided', () => { + const testable = component as ChartEditComponentTestable; + testable.queryName.set('Test'); + testable.queryText.set('SELECT 1'); + testable.saving.set(false); + expect(testable.canSave()).toBe(true); + }); + + it('should return false when saving', () => { + const testable = component as ChartEditComponentTestable; + testable.queryName.set('Test'); + testable.queryText.set('SELECT 1'); + testable.saving.set(true); + expect(testable.canSave()).toBe(false); + }); + }); + + describe('canTest computed', () => { + it('should return false when query is empty', () => { + const testable = component as ChartEditComponentTestable; + testable.queryText.set(''); + expect(testable.canTest()).toBe(false); + }); + + it('should return true when query is provided', () => { + const testable = component as ChartEditComponentTestable; + testable.queryText.set('SELECT 1'); + testable.testing.set(false); + expect(testable.canTest()).toBe(true); + }); + + it('should return false when testing', () => { + const testable = component as ChartEditComponentTestable; + testable.queryText.set('SELECT 1'); + testable.testing.set(true); + expect(testable.canTest()).toBe(false); + }); + }); + + describe('testQuery', () => { + it('should call testQuery service method', () => { + const testable = component as ChartEditComponentTestable; + testable.queryText.set('SELECT * FROM users'); + component.testQuery(); + expect(mockSavedQueriesService.testQuery).toHaveBeenCalledWith('conn-1', { + query_text: 'SELECT * FROM users', + }); + }); + + it('should set results and columns after successful test', () => { + const testable = component as ChartEditComponentTestable; + testable.queryText.set('SELECT * FROM users'); + component.testQuery(); + expect(testable.testResults()).toEqual([{ name: 'John', count: 10 }]); + expect(testable.resultColumns()).toEqual(['name', 'count']); + expect(testable.executionTime()).toBe(50); + }); + + it('should auto-select label and value columns', () => { + const testable = component as ChartEditComponentTestable; + testable.queryText.set('SELECT * FROM users'); + component.testQuery(); + expect(testable.labelColumn()).toBe('name'); + expect(testable.valueColumn()).toBe('count'); + }); + }); + + describe('saveQuery', () => { + it('should call createSavedQuery in create mode', () => { + const testable = component as ChartEditComponentTestable; + testable.isEditMode.set(false); + testable.queryName.set('New Query'); + testable.queryText.set('SELECT 1'); + component.saveQuery(); + expect(mockSavedQueriesService.createSavedQuery).toHaveBeenCalledWith('conn-1', { + name: 'New Query', + description: undefined, + query_text: 'SELECT 1', + }); + }); + + it('should navigate to charts list after save', () => { + const testable = component as ChartEditComponentTestable; + testable.queryName.set('New Query'); + testable.queryText.set('SELECT 1'); + component.saveQuery(); + expect(router.navigate).toHaveBeenCalledWith(['/charts', 'conn-1']); + }); + }); + + describe('cancel', () => { + it('should navigate to charts list', () => { + component.cancel(); + expect(router.navigate).toHaveBeenCalledWith(['/charts', 'conn-1']); + }); + }); + + describe('onCodeChange', () => { + it('should update queryText', () => { + const testable = component as ChartEditComponentTestable; + component.onCodeChange('SELECT * FROM table'); + expect(testable.queryText()).toBe('SELECT * FROM table'); + }); + }); + + describe('hasChartData computed', () => { + it('should return false when no results', () => { + const testable = component as ChartEditComponentTestable; + testable.testResults.set([]); + expect(testable.hasChartData()).toBe(false); + }); + + it('should return false when no columns selected', () => { + const testable = component as ChartEditComponentTestable; + testable.testResults.set([{ name: 'John' }]); + testable.labelColumn.set(''); + testable.valueColumn.set(''); + expect(testable.hasChartData()).toBe(false); + }); + + it('should return true when results and columns are set', () => { + const testable = component as ChartEditComponentTestable; + testable.testResults.set([{ name: 'John', count: 10 }]); + testable.labelColumn.set('name'); + testable.valueColumn.set('count'); + expect(testable.hasChartData()).toBe(true); + }); + }); +}); diff --git a/frontend/src/app/components/charts/chart-edit/chart-edit.component.ts b/frontend/src/app/components/charts/chart-edit/chart-edit.component.ts new file mode 100644 index 000000000..1e3b216cc --- /dev/null +++ b/frontend/src/app/components/charts/chart-edit/chart-edit.component.ts @@ -0,0 +1,225 @@ +import { CommonModule } from '@angular/common'; +import { Component, computed, effect, inject, OnInit, signal } from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { FormsModule } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { MatSelectModule } from '@angular/material/select'; +import { MatTableModule } from '@angular/material/table'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { Title } from '@angular/platform-browser'; +import { ActivatedRoute, Router, RouterModule } from '@angular/router'; +import { CodeEditorModule } from '@ngstack/code-editor'; +import { Angulartics2 } from 'angulartics2'; +import { finalize } from 'rxjs/operators'; +import { ChartType, TestQueryResult } from 'src/app/models/saved-query'; +import { ConnectionsService } from 'src/app/services/connections.service'; +import { SavedQueriesService } from 'src/app/services/saved-queries.service'; +import { UiSettingsService } from 'src/app/services/ui-settings.service'; +import { AlertComponent } from '../../ui-components/alert/alert.component'; +import { ChartPreviewComponent } from '../chart-preview/chart-preview.component'; + +@Component({ + selector: 'app-chart-edit', + templateUrl: './chart-edit.component.html', + styleUrls: ['./chart-edit.component.css'], + imports: [ + CommonModule, + FormsModule, + RouterModule, + MatButtonModule, + MatIconModule, + MatInputModule, + MatFormFieldModule, + MatSelectModule, + MatTableModule, + MatTooltipModule, + MatProgressSpinnerModule, + CodeEditorModule, + ChartPreviewComponent, + AlertComponent, + ], +}) +export class ChartEditComponent implements OnInit { + protected connectionId = signal(''); + protected queryId = signal(''); + protected isEditMode = signal(false); + protected loading = signal(true); + protected saving = signal(false); + protected testing = signal(false); + + protected queryName = signal(''); + protected queryDescription = signal(''); + protected queryText = signal(''); + + protected testResults = signal[]>([]); + protected resultColumns = signal([]); + protected executionTime = signal(null); + protected showResults = signal(false); + + protected chartType = signal('bar'); + protected labelColumn = signal(''); + protected valueColumn = signal(''); + + public chartTypes: { value: ChartType; label: string }[] = [ + { value: 'bar', label: 'Bar Chart' }, + { value: 'line', label: 'Line Chart' }, + { value: 'pie', label: 'Pie Chart' }, + { value: 'doughnut', label: 'Doughnut Chart' }, + { value: 'polarArea', label: 'Polar Area Chart' }, + ]; + + // Use a signal for codeModel to ensure change detection works on load + // Only update this signal when loading a query, not during typing (to preserve cursor position) + protected codeModel = signal({ + language: 'sql', + uri: 'query.sql', + value: '', + }); + + public codeEditorOptions = { + minimap: { enabled: false }, + automaticLayout: true, + scrollBeyondLastLine: false, + wordWrap: 'on' as const, + lineNumbers: 'on' as const, + }; + public codeEditorTheme = 'vs-dark'; + + protected canSave = computed(() => !!this.queryName().trim() && !!this.queryText().trim() && !this.saving()); + + protected canTest = computed(() => !!this.queryText().trim() && !this.testing()); + + protected hasChartData = computed( + () => this.testResults().length > 0 && !!this.labelColumn() && !!this.valueColumn(), + ); + + private _savedQueries = inject(SavedQueriesService); + private _connections = inject(ConnectionsService); + private _uiSettings = inject(UiSettingsService); + private route = inject(ActivatedRoute); + private router = inject(Router); + private angulartics2 = inject(Angulartics2); + private title = inject(Title); + + private connectionTitle = toSignal(this._connections.getCurrentConnectionTitle(), { initialValue: '' }); + + constructor() { + // Page title effect + effect(() => { + const title = this.connectionTitle(); + const pageTitle = this.isEditMode() ? 'Edit Query' : 'Create Query'; + this.title.setTitle(`${pageTitle} | ${title || 'Rocketadmin'}`); + }); + } + + ngOnInit(): void { + this.connectionId.set(this.route.snapshot.paramMap.get('connection-id') || ''); + this.queryId.set(this.route.snapshot.paramMap.get('query-id') || ''); + this.isEditMode.set(!!this.queryId()); + + this.codeEditorTheme = this._uiSettings.editorTheme; + + if (this.isEditMode()) { + this.loadSavedQuery(); + } else { + this.loading.set(false); + } + } + + loadSavedQuery(): void { + this.loading.set(true); + this._savedQueries + .fetchSavedQuery(this.connectionId(), this.queryId()) + .pipe(finalize(() => this.loading.set(false))) + .subscribe((query) => { + if (query) { + this.queryName.set(query.name); + this.queryDescription.set(query.description || ''); + this.queryText.set(query.query_text); + // Set codeModel value for Monaco editor (only on load, not during typing) + this.codeModel.set({ language: 'sql', uri: 'query.sql', value: query.query_text }); + // Automatically test the query to show chart preview + this.testQuery(); + } + }); + } + + onCodeChange(value: string): void { + this.queryText.set(value); + } + + testQuery(): void { + if (!this.queryText().trim()) { + return; + } + + this.testing.set(true); + this.showResults.set(false); + this._savedQueries + .testQuery(this.connectionId(), { query_text: this.queryText() }) + .pipe(finalize(() => this.testing.set(false))) + .subscribe((result: TestQueryResult) => { + if (result) { + this.testResults.set(result.data); + this.executionTime.set(result.execution_time_ms); + this.resultColumns.set(result.data.length > 0 ? Object.keys(result.data[0]) : []); + this.showResults.set(true); + + if (this.resultColumns().length > 0 && !this.labelColumn()) { + this.labelColumn.set(this.resultColumns()[0]); + } + if (this.resultColumns().length > 1 && !this.valueColumn()) { + this.valueColumn.set(this.resultColumns()[1]); + } + } + }); + + this.angulartics2.eventTrack.next({ + action: 'Charts: test query executed', + }); + } + + saveQuery(): void { + if (!this.queryName().trim() || !this.queryText().trim()) { + return; + } + + this.saving.set(true); + + const payload = { + name: this.queryName(), + description: this.queryDescription() || undefined, + query_text: this.queryText(), + }; + + if (this.isEditMode()) { + this._savedQueries + .updateSavedQuery(this.connectionId(), this.queryId(), payload) + .pipe(finalize(() => this.saving.set(false))) + .subscribe(() => { + this.router.navigate(['/charts', this.connectionId()]); + }); + this.angulartics2.eventTrack.next({ + action: 'Charts: saved query updated', + }); + } else { + this._savedQueries + .createSavedQuery(this.connectionId(), payload) + .pipe(finalize(() => this.saving.set(false))) + .subscribe(() => { + this.router.navigate(['/charts', this.connectionId()]); + }); + this.angulartics2.eventTrack.next({ + action: 'Charts: saved query created', + }); + } + } + + cancel(): void { + this.router.navigate(['/charts', this.connectionId()]); + } +} diff --git a/frontend/src/app/components/charts/chart-preview/chart-preview.component.css b/frontend/src/app/components/charts/chart-preview/chart-preview.component.css new file mode 100644 index 000000000..6f268a57f --- /dev/null +++ b/frontend/src/app/components/charts/chart-preview/chart-preview.component.css @@ -0,0 +1,24 @@ +.chart-preview { + width: 100%; + height: 250px; + position: relative; +} + +.chart-preview canvas { + max-width: 100%; + max-height: 100%; +} + +.no-data { + display: flex; + align-items: center; + justify-content: center; + height: 200px; + color: rgba(0, 0, 0, 0.54); +} + +@media (prefers-color-scheme: dark) { + .no-data { + color: rgba(255, 255, 255, 0.54); + } +} diff --git a/frontend/src/app/components/charts/chart-preview/chart-preview.component.html b/frontend/src/app/components/charts/chart-preview/chart-preview.component.html new file mode 100644 index 000000000..adf13ac54 --- /dev/null +++ b/frontend/src/app/components/charts/chart-preview/chart-preview.component.html @@ -0,0 +1,11 @@ +
+ + +
+ +
+

No chart data available

+
diff --git a/frontend/src/app/components/charts/chart-preview/chart-preview.component.ts b/frontend/src/app/components/charts/chart-preview/chart-preview.component.ts new file mode 100644 index 000000000..e7f4dc118 --- /dev/null +++ b/frontend/src/app/components/charts/chart-preview/chart-preview.component.ts @@ -0,0 +1,96 @@ +import { CommonModule } from '@angular/common'; +import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { ChartConfiguration, ChartData, ChartType as ChartJsType } from 'chart.js'; +import { BaseChartDirective } from 'ng2-charts'; +import { ChartType } from 'src/app/models/saved-query'; + +@Component({ + selector: 'app-chart-preview', + templateUrl: './chart-preview.component.html', + styleUrls: ['./chart-preview.component.css'], + imports: [CommonModule, BaseChartDirective], +}) +export class ChartPreviewComponent implements OnChanges { + @Input() chartType: ChartType = 'bar'; + @Input() data: Record[] = []; + @Input() labelColumn = ''; + @Input() valueColumn = ''; + + public chartData: ChartData | null = null; + public chartOptions: ChartConfiguration['options'] = { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + display: true, + position: 'top', + }, + }, + }; + + private colorPalette = [ + 'rgba(99, 102, 241, 0.8)', + 'rgba(168, 85, 247, 0.8)', + 'rgba(236, 72, 153, 0.8)', + 'rgba(244, 63, 94, 0.8)', + 'rgba(251, 146, 60, 0.8)', + 'rgba(234, 179, 8, 0.8)', + 'rgba(34, 197, 94, 0.8)', + 'rgba(6, 182, 212, 0.8)', + 'rgba(59, 130, 246, 0.8)', + 'rgba(139, 92, 246, 0.8)', + ]; + + ngOnChanges(changes: SimpleChanges): void { + if (changes['data'] || changes['labelColumn'] || changes['valueColumn'] || changes['chartType']) { + this.updateChartData(); + } + } + + get mappedChartType(): ChartJsType { + return this.chartType as ChartJsType; + } + + private updateChartData(): void { + if (!this.data.length || !this.labelColumn || !this.valueColumn) { + this.chartData = null; + return; + } + + const labels = this.data.map((row) => String(row[this.labelColumn] ?? '')); + const values = this.data.map((row) => { + const val = row[this.valueColumn]; + return typeof val === 'number' ? val : parseFloat(String(val)) || 0; + }); + + const isPieType = ['pie', 'doughnut', 'polarArea'].includes(this.chartType); + + if (isPieType) { + this.chartData = { + labels, + datasets: [ + { + data: values, + backgroundColor: this.colorPalette.slice(0, values.length), + borderColor: this.colorPalette.slice(0, values.length).map((c) => c.replace('0.8', '1')), + borderWidth: 1, + }, + ], + }; + } else { + this.chartData = { + labels, + datasets: [ + { + label: this.valueColumn, + data: values, + backgroundColor: this.colorPalette[0], + borderColor: this.colorPalette[0].replace('0.8', '1'), + borderWidth: 1, + fill: this.chartType === 'line', + }, + ], + }; + } + } +} diff --git a/frontend/src/app/components/charts/charts-list/charts-list.component.css b/frontend/src/app/components/charts/charts-list/charts-list.component.css new file mode 100644 index 000000000..ec54d827d --- /dev/null +++ b/frontend/src/app/components/charts/charts-list/charts-list.component.css @@ -0,0 +1,208 @@ +.charts-page { + margin: 3em auto; + padding: 0 clamp(200px, 20vw, 300px); +} + +@media (width <= 600px) { + .charts-page { + padding: 0 9vw; + } +} + +.charts-header { + margin-bottom: 32px; +} + +.charts-description { + color: rgba(0, 0, 0, 0.64); + margin-top: 8px; +} + +@media (prefers-color-scheme: dark) { + .charts-description { + color: rgba(255, 255, 255, 0.7); + } +} + +.charts-toolbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + margin-bottom: 24px; +} + +@media (width <= 600px) { + .charts-toolbar { + flex-direction: column; + align-items: stretch; + } +} + +.search-field { + flex: 1; + max-width: 400px; +} + +@media (width <= 600px) { + .search-field { + max-width: 100%; + } +} + +.charts-table { + width: 100%; + margin-bottom: 16px; +} + +.charts-cell_name { + max-width: 250px; +} + +.name-text { + font-weight: 500; +} + +.description-text { + color: rgba(0, 0, 0, 0.87); +} + +@media (prefers-color-scheme: dark) { + .description-text { + color: rgba(255, 255, 255, 0.87); + } +} + +.no-description { + color: rgba(0, 0, 0, 0.38); + font-style: italic; +} + +@media (prefers-color-scheme: dark) { + .no-description { + color: rgba(255, 255, 255, 0.38); + } +} + +.charts-cell_actions { + text-align: right; +} + +.no-charts { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 64px 24px; + text-align: center; + background-color: rgba(0, 0, 0, 0.02); + border-radius: 8px; +} + +@media (prefers-color-scheme: dark) { + .no-charts { + background-color: rgba(255, 255, 255, 0.05); + } +} + +.no-charts-icon { + font-size: 64px; + width: 64px; + height: 64px; + color: rgba(0, 0, 0, 0.26); + margin-bottom: 16px; +} + +@media (prefers-color-scheme: dark) { + .no-charts-icon { + color: rgba(255, 255, 255, 0.3); + } +} + +.no-charts h3 { + margin: 0 0 8px 0; + color: rgba(0, 0, 0, 0.87); +} + +@media (prefers-color-scheme: dark) { + .no-charts h3 { + color: rgba(255, 255, 255, 0.87); + } +} + +.no-charts p { + margin: 0 0 16px 0; + color: rgba(0, 0, 0, 0.54); +} + +@media (prefers-color-scheme: dark) { + .no-charts p { + color: rgba(255, 255, 255, 0.54); + } +} + +.delete-action { + color: #c62828; +} + +@media (prefers-color-scheme: dark) { + .delete-action { + color: #ef5350; + } +} + +/* Responsive table styles */ +@media (width <= 600px) { + .charts-table { + display: grid; + grid-template-columns: auto 1fr; + max-width: 100%; + } + + .charts-table-heading { + display: none; + } + + .charts-table ::ng-deep tbody { + display: grid; + grid-template-columns: subgrid; + grid-column: 1 / 3; + } + + .charts-row { + display: grid; + grid-template-columns: subgrid; + grid-column: 1 / 3; + grid-gap: 12px 28px; + border-bottom-color: var(--mat-table-row-item-outline-color, rgba(0, 0, 0, 0.12)); + border-bottom-width: var(--mat-table-row-item-outline-width, 1px); + border-bottom-style: solid; + height: auto; + padding: 20px 0; + } + + .charts-cell { + display: grid; + grid-template-columns: subgrid; + grid-column: 1 / 3; + border-bottom: none; + } + + .charts-cell::before { + content: attr(data-label); + display: inline-block; + font-weight: bold; + white-space: nowrap; + } + + .charts-cell_actions { + grid-column: 1 / span 3; + display: flex; + justify-content: flex-end; + border-bottom: none; + } + + .charts-cell_actions::before { + display: none; + } +} diff --git a/frontend/src/app/components/charts/charts-list/charts-list.component.html b/frontend/src/app/components/charts/charts-list/charts-list.component.html new file mode 100644 index 000000000..bfcb37cee --- /dev/null +++ b/frontend/src/app/components/charts/charts-list/charts-list.component.html @@ -0,0 +1,111 @@ + + +
+
+

Saved Queries

+

+ Create and manage saved SQL queries with chart visualizations. +

+
+ +
+ + Search queries + + search + + + + add + Create Query + +
+ + + +
+ bar_chart +

No saved queries found

+

No queries match your search criteria.

+

Create your first saved query to visualize your data.

+ + add + Create Query + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name + {{query.name}} + Description + {{query.description}} + No description + Last Updated + {{query.updated_at | date:'medium'}} + + + + + edit + Edit + + + + +
+
diff --git a/frontend/src/app/components/charts/charts-list/charts-list.component.spec.ts b/frontend/src/app/components/charts/charts-list/charts-list.component.spec.ts new file mode 100644 index 000000000..686340bd0 --- /dev/null +++ b/frontend/src/app/components/charts/charts-list/charts-list.component.spec.ts @@ -0,0 +1,180 @@ +import { provideHttpClient } from '@angular/common/http'; +import { provideHttpClientTesting } from '@angular/common/http/testing'; +import { Signal, signal, WritableSignal } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { MatDialog } from '@angular/material/dialog'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { ActivatedRoute } from '@angular/router'; +import { RouterTestingModule } from '@angular/router/testing'; +import { Angulartics2Module } from 'angulartics2'; +import { of } from 'rxjs'; +import { SavedQuery } from 'src/app/models/saved-query'; +import { ConnectionsService } from 'src/app/services/connections.service'; +import { QueryUpdateEvent, SavedQueriesService } from 'src/app/services/saved-queries.service'; +import { ChartDeleteDialogComponent } from '../chart-delete-dialog/chart-delete-dialog.component'; +import { ChartsListComponent } from './charts-list.component'; + +type ChartsListComponentTestable = ChartsListComponent & { + savedQueries: Signal; + loading: Signal; + searchQuery: WritableSignal; + filteredQueries: Signal; +}; + +describe('ChartsListComponent', () => { + let component: ChartsListComponent; + let fixture: ComponentFixture; + let mockSavedQueriesService: Partial; + let mockConnectionsService: Partial; + let mockDialog: Partial; + let queriesUpdatedSignal: WritableSignal; + let savedQueriesSignal: WritableSignal; + let savedQueriesLoadingSignal: WritableSignal; + + const mockSavedQuery: SavedQuery = { + id: '1', + name: 'Test Query', + description: 'Test description', + query_text: 'SELECT * FROM users', + connection_id: 'conn-1', + created_at: '2024-01-01', + updated_at: '2024-01-01', + }; + + beforeEach(async () => { + queriesUpdatedSignal = signal(''); + savedQueriesSignal = signal([mockSavedQuery]); + savedQueriesLoadingSignal = signal(false); + + mockSavedQueriesService = { + savedQueries: savedQueriesSignal.asReadonly(), + savedQueriesLoading: savedQueriesLoadingSignal.asReadonly(), + queriesUpdated: queriesUpdatedSignal.asReadonly(), + setActiveConnection: vi.fn(), + refreshSavedQueries: vi.fn(), + }; + + mockConnectionsService = { + getCurrentConnectionTitle: vi.fn().mockReturnValue(of('Test Connection')), + }; + + mockDialog = { + open: vi.fn(), + }; + + await TestBed.configureTestingModule({ + imports: [ + ChartsListComponent, + BrowserAnimationsModule, + MatSnackBarModule, + RouterTestingModule, + Angulartics2Module.forRoot(), + ], + providers: [ + provideHttpClient(), + provideHttpClientTesting(), + { provide: SavedQueriesService, useValue: mockSavedQueriesService }, + { provide: ConnectionsService, useValue: mockConnectionsService }, + { provide: MatDialog, useValue: mockDialog }, + { + provide: ActivatedRoute, + useValue: { + snapshot: { + paramMap: { + get: () => 'conn-1', + }, + }, + }, + }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(ChartsListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should set active connection on init', () => { + expect(mockSavedQueriesService.setActiveConnection).toHaveBeenCalledWith('conn-1'); + }); + + it('should set page title on init', () => { + expect(mockConnectionsService.getCurrentConnectionTitle).toHaveBeenCalled(); + }); + + it('should initialize with loading from service', () => { + const testable = component as ChartsListComponentTestable; + expect(testable.loading()).toBe(false); + }); + + it('should have correct displayed columns', () => { + expect(component.displayedColumns).toEqual(['name', 'description', 'updatedAt', 'actions']); + }); + + describe('filteredQueries computed', () => { + it('should show all queries when search is empty', () => { + const testable = component as ChartsListComponentTestable; + savedQueriesSignal.set([mockSavedQuery]); + testable.searchQuery.set(''); + expect(testable.filteredQueries()).toEqual([mockSavedQuery]); + }); + + it('should filter by name', () => { + const testable = component as ChartsListComponentTestable; + savedQueriesSignal.set([mockSavedQuery]); + testable.searchQuery.set('Test'); + expect(testable.filteredQueries()).toEqual([mockSavedQuery]); + }); + + it('should filter by description', () => { + const testable = component as ChartsListComponentTestable; + savedQueriesSignal.set([mockSavedQuery]); + testable.searchQuery.set('description'); + expect(testable.filteredQueries()).toEqual([mockSavedQuery]); + }); + + it('should return empty when no match', () => { + const testable = component as ChartsListComponentTestable; + savedQueriesSignal.set([mockSavedQuery]); + testable.searchQuery.set('nonexistent'); + expect(testable.filteredQueries()).toEqual([]); + }); + }); + + describe('openDeleteDialog', () => { + it('should open delete dialog with query data', () => { + component.openDeleteDialog(mockSavedQuery); + expect(mockDialog.open).toHaveBeenCalledWith(ChartDeleteDialogComponent, { + width: '400px', + data: { query: mockSavedQuery, connectionId: 'conn-1' }, + }); + }); + }); + + describe('queriesUpdated effect', () => { + it('should refresh queries when queriesUpdated signal changes', () => { + vi.mocked(mockSavedQueriesService.refreshSavedQueries!).mockClear(); + + // Trigger the signal change + queriesUpdatedSignal.set('created'); + TestBed.flushEffects(); + + expect(mockSavedQueriesService.refreshSavedQueries).toHaveBeenCalled(); + }); + + it('should not refresh queries when queriesUpdated signal is empty', () => { + vi.mocked(mockSavedQueriesService.refreshSavedQueries!).mockClear(); + + // Set empty value + queriesUpdatedSignal.set(''); + TestBed.flushEffects(); + + expect(mockSavedQueriesService.refreshSavedQueries).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/frontend/src/app/components/charts/charts-list/charts-list.component.ts b/frontend/src/app/components/charts/charts-list/charts-list.component.ts new file mode 100644 index 000000000..81f0f0e49 --- /dev/null +++ b/frontend/src/app/components/charts/charts-list/charts-list.component.ts @@ -0,0 +1,113 @@ +import { CommonModule } from '@angular/common'; +import { Component, computed, effect, inject, OnInit, signal } from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { FormsModule } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialog } from '@angular/material/dialog'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatTableModule } from '@angular/material/table'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { Title } from '@angular/platform-browser'; +import { ActivatedRoute, RouterModule } from '@angular/router'; +import { Angulartics2 } from 'angulartics2'; +import { SavedQuery } from 'src/app/models/saved-query'; +import { ConnectionsService } from 'src/app/services/connections.service'; +import { SavedQueriesService } from 'src/app/services/saved-queries.service'; +import { PlaceholderTableDataComponent } from '../../skeletons/placeholder-table-data/placeholder-table-data.component'; +import { AlertComponent } from '../../ui-components/alert/alert.component'; +import { ChartDeleteDialogComponent } from '../chart-delete-dialog/chart-delete-dialog.component'; + +@Component({ + selector: 'app-charts-list', + templateUrl: './charts-list.component.html', + styleUrls: ['./charts-list.component.css'], + imports: [ + CommonModule, + FormsModule, + RouterModule, + MatTableModule, + MatButtonModule, + MatIconModule, + MatMenuModule, + MatInputModule, + MatFormFieldModule, + MatTooltipModule, + MatDividerModule, + PlaceholderTableDataComponent, + AlertComponent, + ], +}) +export class ChartsListComponent implements OnInit { + protected searchQuery = signal(''); + protected connectionId = signal(''); + public displayedColumns = ['name', 'description', 'updatedAt', 'actions']; + + private _savedQueries = inject(SavedQueriesService); + private _connections = inject(ConnectionsService); + private route = inject(ActivatedRoute); + private dialog = inject(MatDialog); + private angulartics2 = inject(Angulartics2); + private title = inject(Title); + + // Use service signals for saved queries and loading + protected savedQueries = computed(() => this._savedQueries.savedQueries()); + protected loading = computed(() => this._savedQueries.savedQueriesLoading()); + + protected filteredQueries = computed(() => { + const queries = this.savedQueries(); + const search = this.searchQuery(); + if (!search) return queries; + const query = search.toLowerCase(); + return queries.filter( + (q) => q.name.toLowerCase().includes(query) || (q.description && q.description.toLowerCase().includes(query)), + ); + }); + + private connectionTitle = toSignal(this._connections.getCurrentConnectionTitle(), { initialValue: '' }); + + constructor() { + // Connection title effect + effect(() => { + const title = this.connectionTitle(); + this.title.setTitle(`Charts | ${title || 'Rocketadmin'}`); + }); + + // Queries update effect + effect(() => { + const action = this._savedQueries.queriesUpdated(); + if (action) this._savedQueries.refreshSavedQueries(); + }); + } + + ngOnInit(): void { + const connId = this.route.snapshot.paramMap.get('connection-id') || ''; + this.connectionId.set(connId); + this._savedQueries.setActiveConnection(connId); + } + + trackCreatePageOpened(): void { + this.angulartics2.eventTrack.next({ + action: 'Charts: create chart page opened', + }); + } + + trackEditPageOpened(): void { + this.angulartics2.eventTrack.next({ + action: 'Charts: edit chart page opened', + }); + } + + openDeleteDialog(query: SavedQuery): void { + this.dialog.open(ChartDeleteDialogComponent, { + width: '400px', + data: { query, connectionId: this.connectionId() }, + }); + this.angulartics2.eventTrack.next({ + action: 'Charts: delete chart dialog opened', + }); + } +} diff --git a/frontend/src/app/components/dashboard/db-table-view/db-table-view.component.css b/frontend/src/app/components/dashboard/db-table-view/db-table-view.component.css index 9fd3d514e..374a1f2ef 100644 --- a/frontend/src/app/components/dashboard/db-table-view/db-table-view.component.css +++ b/frontend/src/app/components/dashboard/db-table-view/db-table-view.component.css @@ -193,34 +193,34 @@ } .active-filters { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 8px; - margin-bottom: 12px; + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 12px; } ::ng-deep .active-filters .mat-mdc-chip { - --mdc-chip-container-color: #E8ECEE !important; - --mdc-chip-elevated-container-color: #E8ECEE !important; - --mdc-chip-container-shape-radius: 16px !important; - background-color: #E8ECEE !important; - border-radius: 16px !important; + --mdc-chip-container-color: #e8ecee !important; + --mdc-chip-elevated-container-color: #e8ecee !important; + --mdc-chip-container-shape-radius: 16px !important; + background-color: #e8ecee !important; + border-radius: 16px !important; } ::ng-deep .active-filters .mat-mdc-chip:hover { - --mdc-chip-container-color: #E8ECEE !important; - --mdc-chip-elevated-container-color: #E8ECEE !important; - background-color: #E8ECEE !important; + --mdc-chip-container-color: #e8ecee !important; + --mdc-chip-elevated-container-color: #e8ecee !important; + background-color: #e8ecee !important; } ::ng-deep .active-filters .mdc-evolution-chip__cell { - background-color: #E8ECEE !important; - border-radius: 16px !important; + background-color: #e8ecee !important; + border-radius: 16px !important; } ::ng-deep .active-filters .mdc-evolution-chip__cell:hover { - background-color: #E8ECEE !important; + background-color: #e8ecee !important; } @media (prefers-color-scheme: dark) { @@ -487,91 +487,91 @@ td.mat-cell { /* Sortable header styles */ .sortable-header__content { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - gap: 4px; + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + gap: 4px; } .sortable-header__text { - flex: 1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .sortable-header__button { - opacity: 0; - width: 24px; - height: 24px; - line-height: 24px; - flex-shrink: 0; - transition: opacity 0.2s ease; + opacity: 0; + width: 24px; + height: 24px; + line-height: 24px; + flex-shrink: 0; + transition: opacity 0.2s ease; } .sortable-header:hover .sortable-header__button, .sortable-header_active .sortable-header__button { - opacity: 1; + opacity: 1; } .sortable-header__icon { - font-size: 18px; - width: 18px; - height: 18px; - color: rgba(0, 0, 0, 0.54); + font-size: 18px; + width: 18px; + height: 18px; + color: rgba(0, 0, 0, 0.54); } .sortable-header_active .sortable-header__icon { - color: var(--color-primaryPalette-500); + color: var(--color-primaryPalette-500); } @media (prefers-color-scheme: dark) { - .sortable-header__icon { - color: rgba(255, 255, 255, 0.54); - } + .sortable-header__icon { + color: rgba(255, 255, 255, 0.54); + } - .sortable-header_active .sortable-header__icon { - color: var(--color-primaryPalette-300); - } + .sortable-header_active .sortable-header__icon { + color: var(--color-primaryPalette-300); + } } /* Sort menu styles */ .sort-menu__item { - display: flex; - align-items: center; - gap: 8px; + display: flex; + align-items: center; + gap: 8px; } .sort-menu__item mat-icon { - font-size: 18px; - width: 18px; - height: 18px; + font-size: 18px; + width: 18px; + height: 18px; } .sort-menu__item-content { - display: flex; - align-items: center; - gap: 8px; - padding: 4px 10px; - border-radius: 4px; - margin: -4px -10px; + display: flex; + align-items: center; + gap: 8px; + padding: 4px 10px; + border-radius: 4px; + margin: -4px -10px; } .sort-menu__item-content_active { - background-color: rgba(0, 0, 0, 0.04); + background-color: rgba(0, 0, 0, 0.04); } @media (prefers-color-scheme: dark) { - .sort-menu__item-content_active { - background-color: rgba(255, 255, 255, 0.06); - } + .sort-menu__item-content_active { + background-color: rgba(255, 255, 255, 0.06); + } } .sort-menu__lock-icon { - font-size: 16px; - width: 16px; - height: 16px; + font-size: 16px; + width: 16px; + height: 16px; } .db-table-cell-checkbox { @@ -702,83 +702,84 @@ tr.mat-row:hover { } .hidden { - display: none; + display: none; } /* Columns Menu Drag and Drop Styles */ .columns-list { - max-height: 400px; - overflow-y: auto; - padding: 8px 0; + max-height: 400px; + overflow-y: auto; + padding: 8px 0; } .draggable-column-item { - cursor: move; - display: flex !important; - align-items: center; - justify-content: flex-start; - gap: 0px; - padding: 8px 24px 8px 8px !important; - min-height: 48px !important; - transition: background-color 0.2s ease; + cursor: move; + display: flex !important; + align-items: center; + justify-content: flex-start; + gap: 0px; + padding: 8px 24px 8px 8px !important; + min-height: 48px !important; + transition: background-color 0.2s ease; } .draggable-column-item .drag-handle { - color: #9e9e9e; - cursor: grab; - font-size: 20px; - width: 20px; - height: 20px; - margin-right: 0px; - flex-shrink: 0; + color: #9e9e9e; + cursor: grab; + font-size: 20px; + width: 20px; + height: 20px; + margin-right: 0px; + flex-shrink: 0; } .draggable-column-item ::ng-deep .mat-mdc-checkbox { - align-items: center !important; + align-items: center !important; } .draggable-column-item ::ng-deep .mat-mdc-checkbox-label { - text-align: left; - line-height: 1.5; + text-align: left; + line-height: 1.5; } .draggable-column-item ::ng-deep .mdc-form-field { - align-items: center !important; + align-items: center !important; } .draggable-column-item:active .drag-handle { - cursor: grabbing; + cursor: grabbing; } .draggable-column-item:hover .drag-handle { - color: #616161; + color: #616161; } @media (prefers-color-scheme: dark) { - .draggable-column-item .drag-handle { - color: #757575; - } - - .draggable-column-item:hover .drag-handle { - color: #bdbdbd; - } + .draggable-column-item .drag-handle { + color: #757575; + } + + .draggable-column-item:hover .drag-handle { + color: #bdbdbd; + } } .cdk-drag-preview.draggable-column-item { - box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), - 0 8px 10px 1px rgba(0, 0, 0, 0.14), - 0 3px 14px 2px rgba(0, 0, 0, 0.12); - opacity: 0.9; + box-shadow: + 0 5px 5px -3px rgba(0, 0, 0, 0.2), + 0 8px 10px 1px rgba(0, 0, 0, 0.14), + 0 3px 14px 2px rgba(0, 0, 0, 0.12); + opacity: 0.9; } .cdk-drag-placeholder { - opacity: 0.3; + opacity: 0.3; } .cdk-drag-animating { - transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); + transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); } .columns-list.cdk-drop-list-dragging .draggable-column-item:not(.cdk-drag-placeholder) { - transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); + transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); } diff --git a/frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-panel.component.css b/frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-panel.component.css index e4f4933a0..594bd81ef 100644 --- a/frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-panel.component.css +++ b/frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-panel.component.css @@ -95,7 +95,11 @@ padding-right: 8px !important; } -.saved-filters-tabs ::ng-deep .mat-mdc-standard-chip.mdc-evolution-chip--selected .mdc-evolution-chip__action .mdc-evolution-chip__action__content { +.saved-filters-tabs + ::ng-deep + .mat-mdc-standard-chip.mdc-evolution-chip--selected + .mdc-evolution-chip__action + .mdc-evolution-chip__action__content { margin-left: 0 !important; padding-left: 0 !important; transform: translateX(0) !important; @@ -306,56 +310,56 @@ } ::ng-deep .static-filter-chip .mat-mdc-chip { - --mdc-chip-container-color: #E8ECEE !important; - --mdc-chip-elevated-container-color: #E8ECEE !important; + --mdc-chip-container-color: #e8ecee !important; + --mdc-chip-elevated-container-color: #e8ecee !important; --mdc-chip-container-shape-radius: 16px !important; - background-color: #E8ECEE !important; + background-color: #e8ecee !important; border-radius: 16px !important; pointer-events: none !important; cursor: default !important; } ::ng-deep .static-filter-chip .mat-mdc-chip:hover { - --mdc-chip-container-color: #E8ECEE !important; - --mdc-chip-elevated-container-color: #E8ECEE !important; - background-color: #E8ECEE !important; + --mdc-chip-container-color: #e8ecee !important; + --mdc-chip-elevated-container-color: #e8ecee !important; + background-color: #e8ecee !important; cursor: default !important; } ::ng-deep .static-filter-chip .mat-mdc-chip:active { - --mdc-chip-container-color: #E8ECEE !important; - --mdc-chip-elevated-container-color: #E8ECEE !important; - background-color: #E8ECEE !important; + --mdc-chip-container-color: #e8ecee !important; + --mdc-chip-elevated-container-color: #e8ecee !important; + background-color: #e8ecee !important; cursor: default !important; } ::ng-deep .static-filter-chip .mdc-evolution-chip__cell { - background-color: #E8ECEE !important; + background-color: #e8ecee !important; border-radius: 16px !important; } ::ng-deep .static-filter-chip .mdc-evolution-chip__cell:hover { - background-color: #E8ECEE !important; + background-color: #e8ecee !important; } ::ng-deep .static-filter-chip .mat-mdc-chip.mdc-evolution-chip--with-primary-icon { - --mdc-chip-container-color: #E8ECEE !important; - --mdc-chip-elevated-container-color: #E8ECEE !important; - background-color: #E8ECEE !important; + --mdc-chip-container-color: #e8ecee !important; + --mdc-chip-elevated-container-color: #e8ecee !important; + background-color: #e8ecee !important; pointer-events: none !important; } ::ng-deep .static-filter-chip .mat-mdc-chip.mdc-evolution-chip--with-primary-icon:hover { - --mdc-chip-container-color: #E8ECEE !important; - --mdc-chip-elevated-container-color: #E8ECEE !important; - background-color: #E8ECEE !important; + --mdc-chip-container-color: #e8ecee !important; + --mdc-chip-elevated-container-color: #e8ecee !important; + background-color: #e8ecee !important; cursor: default !important; } ::ng-deep .static-filter-chip .mat-mdc-chip.mdc-evolution-chip--with-primary-icon:active { - --mdc-chip-container-color: #E8ECEE !important; - --mdc-chip-elevated-container-color: #E8ECEE !important; - background-color: #E8ECEE !important; + --mdc-chip-container-color: #e8ecee !important; + --mdc-chip-elevated-container-color: #e8ecee !important; + background-color: #e8ecee !important; cursor: default !important; } diff --git a/frontend/src/app/models/saved-query.ts b/frontend/src/app/models/saved-query.ts new file mode 100644 index 000000000..12aef8d94 --- /dev/null +++ b/frontend/src/app/models/saved-query.ts @@ -0,0 +1,40 @@ +export interface SavedQuery { + id: string; + name: string; + description: string | null; + query_text: string; + connection_id: string; + created_at: string; + updated_at: string; +} + +export interface CreateSavedQueryPayload { + name: string; + description?: string; + query_text: string; +} + +export interface UpdateSavedQueryPayload { + name?: string; + description?: string; + query_text?: string; +} + +export interface QueryExecutionResult { + query_id: string; + query_name: string; + data: Record[]; + execution_time_ms: number; +} + +export interface TestQueryPayload { + query_text: string; + tableName?: string; +} + +export interface TestQueryResult { + data: Record[]; + execution_time_ms: number; +} + +export type ChartType = 'bar' | 'line' | 'pie' | 'doughnut' | 'polarArea'; diff --git a/frontend/src/app/services/connections.service.spec.ts b/frontend/src/app/services/connections.service.spec.ts index 151eb7ea3..1c51e304c 100644 --- a/frontend/src/app/services/connections.service.spec.ts +++ b/frontend/src/app/services/connections.service.spec.ts @@ -253,18 +253,18 @@ describe('ConnectionsService', () => { expect(service.currentTab).toEqual('dashboard'); }); - it('should get visible tabs dashboard and audit in any case', () => { - expect(service.visibleTabs).toEqual(['dashboard', 'audit']); + it('should get visible tabs dashboard, charts and audit in any case', () => { + expect(service.visibleTabs).toEqual(['dashboard', 'charts', 'audit']); }); - it('should get visible tabs dashboard, audit and permissions if groupsAccessLevel is true', () => { + it('should get visible tabs dashboard, charts, audit and permissions if groupsAccessLevel is true', () => { service.groupsAccessLevel = true; - expect(service.visibleTabs).toEqual(['dashboard', 'audit', 'permissions']); + expect(service.visibleTabs).toEqual(['dashboard', 'charts', 'audit', 'permissions']); }); - it('should get visible tabs dashboard, audit, edit-db and connection-settings if connectionAccessLevel is edit', () => { + it('should get visible tabs dashboard, charts, audit, connection-settings and edit-db if connectionAccessLevel is edit', () => { service.connectionAccessLevel = AccessLevel.Edit; - expect(service.visibleTabs).toEqual(['dashboard', 'audit', 'connection-settings', 'edit-db']); + expect(service.visibleTabs).toEqual(['dashboard', 'charts', 'audit', 'connection-settings', 'edit-db']); }); it('should call fetchConnections', () => { diff --git a/frontend/src/app/services/connections.service.ts b/frontend/src/app/services/connections.service.ts index 5d949638a..160f60b37 100644 --- a/frontend/src/app/services/connections.service.ts +++ b/frontend/src/app/services/connections.service.ts @@ -1,538 +1,535 @@ -import { AlertActionType, AlertType } from '../models/alert'; -import { BehaviorSubject, EMPTY, throwError } from 'rxjs'; -import { Connection, ConnectionSettings, ConnectionType, DBtype } from '../models/connection'; +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { NavigationEnd, Router } from '@angular/router'; import { IColorConfig, NgxThemeService } from '@brumeilde/ngx-theme'; -import { NavigationEnd, Router, } from '@angular/router'; +import { BehaviorSubject, EMPTY, throwError } from 'rxjs'; import { catchError, filter, map } from 'rxjs/operators'; - +import { AlertActionType, AlertType } from '../models/alert'; +import { Connection, ConnectionSettings, ConnectionType, DBtype } from '../models/connection'; import { AccessLevel } from '../models/user'; -import { HttpClient } from '@angular/common/http'; -import { Injectable } from '@angular/core'; import { MasterPasswordService } from './master-password.service'; import { NotificationsService } from './notifications.service'; interface LogParams { - connectionID: string, - tableName?: string, - userEmail?: string, - requstedPage?: number, - chunkSize?: number, + connectionID: string; + tableName?: string; + userEmail?: string; + requstedPage?: number; + chunkSize?: number; } -type Palettes = { primaryPalette: string, accentedPalette: string }; +type Palettes = { primaryPalette: string; accentedPalette: string }; type Colors = { myColorName: string }; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class ConnectionsService { - public connectionID: string | null = null; - public connectionInitialState: Connection = Object.freeze({ - id: null, - type: DBtype.MySQL, - host: '', - port: '3306', - sid: '', - username: '', - password: '', - database: '', - authSource: '', - title: '', - ssh: false, - privateSSHKey: '', - sshHost: '', - sshPort: '', - sshUsername: '', - ssl: false, - cert: '', - masterEncryption: false, - azure_encryption: false, - connectionType: ConnectionType.Direct, - signing_key: null - }); - public connection: Connection; - public connectionAccessLevel: AccessLevel; - public groupsAccessLevel: boolean; - public currentPage: string; - public isCustomAccentedColor: boolean; - public defaultDisplayTable: string; - public ownConnections: Connection[] = null; - public testConnections: Connection[] = null; - - private connectionNameSubject: BehaviorSubject = new BehaviorSubject('Rocketadmin'); - private connectionSigningKeySubject: BehaviorSubject = new BehaviorSubject(null); - private connectionsSubject: BehaviorSubject = new BehaviorSubject([]); - - public cast = this.connectionsSubject.asObservable(); - - constructor( - private _http: HttpClient, - private router: Router, - private _notifications: NotificationsService, - private _masterPassword: MasterPasswordService, - public _themeService: NgxThemeService> - ) { - this.connection = {...this.connectionInitialState}; - this.router = router; - this.router.events + public connectionID: string | null = null; + public connectionInitialState: Connection = Object.freeze({ + id: null, + type: DBtype.MySQL, + host: '', + port: '3306', + sid: '', + username: '', + password: '', + database: '', + authSource: '', + title: '', + ssh: false, + privateSSHKey: '', + sshHost: '', + sshPort: '', + sshUsername: '', + ssl: false, + cert: '', + masterEncryption: false, + azure_encryption: false, + connectionType: ConnectionType.Direct, + signing_key: null, + }); + public connection: Connection; + public connectionAccessLevel: AccessLevel; + public groupsAccessLevel: boolean; + public currentPage: string; + public isCustomAccentedColor: boolean; + public defaultDisplayTable: string; + public ownConnections: Connection[] = null; + public testConnections: Connection[] = null; + + private connectionNameSubject: BehaviorSubject = new BehaviorSubject('Rocketadmin'); + private connectionSigningKeySubject: BehaviorSubject = new BehaviorSubject(null); + private connectionsSubject: BehaviorSubject = new BehaviorSubject([]); + + public cast = this.connectionsSubject.asObservable(); + + constructor( + private _http: HttpClient, + private router: Router, + private _notifications: NotificationsService, + private _masterPassword: MasterPasswordService, + public _themeService: NgxThemeService>, + ) { + this.connection = { ...this.connectionInitialState }; + this.router = router; + this.router.events .pipe( - filter( - (event) : boolean => { - return( event instanceof NavigationEnd ); - } - ) + filter((event): boolean => { + return event instanceof NavigationEnd; + }), ) - .subscribe( - ( _event: NavigationEnd ) : void => { - const urlConnectionID = this.router.routerState.snapshot.root.firstChild.paramMap.get('connection-id'); - this.currentPage = this.router.routerState.snapshot.root.firstChild.url[0].path; - this.setConnectionID(urlConnectionID); - this.setConnectionInfo(urlConnectionID); - this._notifications.resetAlert(); + .subscribe((_event: NavigationEnd): void => { + const urlConnectionID = this.router.routerState.snapshot.root.firstChild.paramMap.get('connection-id'); + this.currentPage = this.router.routerState.snapshot.root.firstChild.url[0].path; + this.setConnectionID(urlConnectionID); + this.setConnectionInfo(urlConnectionID); + this._notifications.resetAlert(); + }); + } + + get currentConnectionID() { + return this.connectionID; + } + + get currentConnectionName() { + return this.defineConnectionTitle(this.connection); + } + + get defaultTableToOpen() { + return this.defaultDisplayTable; + } + + get currentConnection() { + return this.connection; + } + + get currentConnectionAccessLevel() { + return this.connectionAccessLevel; + } + + get currentConnectionGroupAccessLevel() { + return this.groupsAccessLevel; + } + + get currentTab() { + return this.currentPage; + } + + get visibleTabs() { + let tabs = ['dashboard', 'charts', 'audit']; + if (this.groupsAccessLevel) tabs.push('permissions'); + if (this.isPermitted(this.connectionAccessLevel)) tabs.push('connection-settings', 'edit-db'); + return tabs; + } + + get ownConnectionsList() { + return this.ownConnections; + } + + get testConnectionsList() { + return this.testConnections; + } + + getCurrentConnectionTitle() { + return this.connectionNameSubject.asObservable(); + } + + getCurrentConnectionSigningKey() { + return this.connectionSigningKeySubject.asObservable(); + } + + setConnectionID(id: string) { + this.connectionID = id; + } + + setConnectionInfo(id: string) { + this.defaultDisplayTable = null; + if (id) { + this.fetchConnection(id).subscribe((res) => { + this.connection = res.connection; + this.connectionAccessLevel = res.accessLevel; + this.groupsAccessLevel = res.groupManagement; + this.connectionNameSubject.next(res.connection.title || res.connection.database); + this.connectionSigningKeySubject.next(res.connection.signing_key); + if (res.connectionProperties) { + this.defaultDisplayTable = res.connectionProperties.default_showing_table; + this.isCustomAccentedColor = !!res.connectionProperties.secondary_color; + this._themeService.updateColors({ + palettes: { + primaryPalette: res.connectionProperties.primary_color, + accentedPalette: res.connectionProperties.secondary_color, + }, + }); + } else { + this.isCustomAccentedColor = false; + this._themeService.updateColors({ palettes: { primaryPalette: '#212121', accentedPalette: '#C177FC' } }); } - ) - ; - } - - get currentConnectionID() { - return this.connectionID; - } - - get currentConnectionName() { - return this.defineConnectionTitle(this.connection); - } - - get defaultTableToOpen() { - return this.defaultDisplayTable; - } - - get currentConnection() { - return this.connection; - } - - get currentConnectionAccessLevel() { - return this.connectionAccessLevel; - } - - get currentConnectionGroupAccessLevel() { - return this.groupsAccessLevel; - } - - get currentTab() { - return this.currentPage; - } - - get visibleTabs() { - let tabs = ['dashboard', 'audit']; - if (this.groupsAccessLevel) tabs.push('permissions'); - if (this.isPermitted(this.connectionAccessLevel)) tabs.push('connection-settings', 'edit-db'); - return tabs; - } - - get ownConnectionsList() { - return this.ownConnections; - } - - get testConnectionsList() { - return this.testConnections; - } - - getCurrentConnectionTitle() { - return this.connectionNameSubject.asObservable(); - } - - getCurrentConnectionSigningKey() { - return this.connectionSigningKeySubject.asObservable(); - } - - setConnectionID(id: string) { - this.connectionID = id; - } - - setConnectionInfo(id: string) { - this.defaultDisplayTable = null; - if (id) { - this.fetchConnection(id).subscribe(res => { - this.connection = res.connection; - this.connectionAccessLevel = res.accessLevel; - this.groupsAccessLevel = res.groupManagement; - this.connectionNameSubject.next(res.connection.title || res.connection.database); - this.connectionSigningKeySubject.next(res.connection.signing_key); - if (res.connectionProperties) { - this.defaultDisplayTable = res.connectionProperties.default_showing_table; - this.isCustomAccentedColor = !!res.connectionProperties.secondary_color; - this._themeService.updateColors({ palettes: { primaryPalette: res.connectionProperties.primary_color, accentedPalette: res.connectionProperties.secondary_color }}); - } else { - this.isCustomAccentedColor = false; - this._themeService.updateColors({ palettes: { primaryPalette: '#212121', accentedPalette: '#C177FC' }}); - } - }); - } else { - this.connection = {...this.connectionInitialState}; - this.isCustomAccentedColor = false; - this._themeService.updateColors({ palettes: { primaryPalette: '#212121', accentedPalette: '#C177FC' }}); - } - - console.log('this.defaultDisplayTable'); - console.log(this.defaultDisplayTable); - } - - isPermitted(accessLevel: AccessLevel) { - return accessLevel === 'edit' || accessLevel === 'readonly' - } - - defineConnectionType(connection) { - if (connection.type?.startsWith('agent_')) { - connection.type = connection.type.slice(6); - connection.connectionType = ConnectionType.Agent; - } else { - connection.connectionType = ConnectionType.Direct; - } - return connection; - } - - defineConnectionTitle(connection: Connection) { - if (!connection.title && connection.masterEncryption) return 'Untitled encrypted connection'; - if (!connection.title && !connection.database) return 'Untitled connection'; - return connection.title || connection.database; - } - - private checkAndSendConversion() { - const now = new Date(); - const firstVisitTime = localStorage.getItem('first_visit_time'); - - if (!firstVisitTime) { - // First visit - record the current date - localStorage.setItem('first_visit_time', now.toISOString()); - return; - } - - const firstVisit = new Date(firstVisitTime); - const daysDifference = Math.floor((now.getTime() - firstVisit.getTime()) / (1000 * 60 * 60 * 24)); - - if (daysDifference >= 7) { - const repeatConversionSent = localStorage.getItem('repeat_conversion_sent'); - - if (!repeatConversionSent) { - localStorage.setItem('repeat_conversion_sent', 'true'); - - // Send conversion event - if (typeof window !== 'undefined' && (window as any).gtag) { - (window as any).gtag('event', 'conversion', { - 'send_to': 'AW-419937947/jqGyCJWo4qobEJv9nsgB', - 'value': 1.0, - 'currency': 'USD', - 'event_callback': () => { - console.log('Conversion event sent successfully'); - } - }); - } - } - } - } - - fetchConnections() { - // Check for first visit and send conversion if needed - this.checkAndSendConversion(); - - return this._http.get('/connections') - .pipe( - map(res => { - const connections = res.connections.map(connectionItem => { - const connection = this.defineConnectionType(connectionItem.connection); - const displayTitle = this.defineConnectionTitle(connectionItem.connection); - return {...connectionItem, connection, displayTitle}; - }); - this.ownConnections = connections.filter(connectionItem => !connectionItem.connection.isTestConnection); - this.testConnections = connections.filter(connectionItem => connectionItem.connection.isTestConnection); - return connections; - }), - catchError((err) => { - console.log(err); - const errorMessage = err.error?.message || 'Unknown error'; - const errorDetails = err.error?.originalMessage || ''; - this._notifications.showAlert(AlertType.Error, {abstract: errorMessage, details: errorDetails}, [ - { - type: AlertActionType.Button, - caption: 'Dismiss', - action: (_id: number) => this._notifications.dismissAlert() - } - ]); - return EMPTY; - }) - ); - } - - fetchConnection(id: string) { - return this._http.get(`/connection/one/${id}`) - .pipe( - map(res => { - const connection = this.defineConnectionType(res.connection); - if (res.connectionProperties) { - this.defaultDisplayTable = res.connectionProperties.default_showing_table; - this._themeService.updateColors({ palettes: { primaryPalette: res.connectionProperties.primary_color, accentedPalette: res.connectionProperties.secondary_color }}); - } else { - this.defaultDisplayTable = null; - this._themeService.updateColors({ palettes: { primaryPalette: '#212121', accentedPalette: '#C177FC' }}); - } - return {...res, connection}; - }), - catchError((err) => { - console.log(err); - if (err.error?.type === 'no_master_key' && this.router.url !== '/connections-list') { - this._masterPassword.showMasterPasswordDialog() - }; - const errorMessage = err.error?.message || 'Unknown error'; - this._notifications.showErrorSnackbar(errorMessage); - return EMPTY; - } - ) - ); - } - - testConnection(connectionID: string, connection: Connection) { - let dbCredentials; - dbCredentials = { - ...connection, - port: parseInt(connection.port, 10), - sshPort: parseInt(connection.sshPort, 10) - }; - - if (connection.connectionType === 'agent') { - dbCredentials.type = `agent_${dbCredentials.type}` - } - - return this._http.post(`/connection/test`, dbCredentials, - {params: { - ...(connectionID ? {connectionId: connectionID} : {}) - }}) - .pipe( - map(res => res), - catchError((err) => { - console.log(err); - const errorMessage = err.error?.message || 'Unknown error'; - const errorDetails = err.error?.originalMessage || ''; - this._notifications.showAlert(AlertType.Error, {abstract: errorMessage, details: errorDetails}, []); - return EMPTY; - } - ) - ); - } - - createConnection(connection: Connection, masterKey: string) { - let dbCredentials; - dbCredentials = { - ...connection, - port: parseInt(connection.port, 10), - sshPort: parseInt(connection.sshPort, 10) - }; - - if (connection.connectionType === 'agent') { - dbCredentials.type = `agent_${dbCredentials.type}` - } - - return this._http.post('/connection', dbCredentials, { - headers: masterKey ? { - masterpwd: masterKey - } : {} - }) - .pipe( - map((res: any) => { - this.connectionsSubject.next(null); - this._masterPassword.checkMasterPassword(connection.masterEncryption, res.id, masterKey); - this._notifications.showSuccessSnackbar('Connection was added successfully.'); - return res; - }), - catchError((err) => { - console.log(err); - const errorMessage = err.error?.message || 'Unknown error'; - const errorDetails = err.error?.originalMessage || ''; - this._notifications.showAlert(AlertType.Error, {abstract: errorMessage, details: errorDetails}, []); - return throwError(() => errorMessage); - }) - ); - } - - updateConnection(connection: Connection, masterKey: string) { - let dbCredentials; - dbCredentials = { - ...connection, - port: parseInt(connection.port, 10), - sshPort: parseInt(connection.sshPort, 10) - }; - - if (connection.connectionType === 'agent') { - dbCredentials.type = `agent_${dbCredentials.type}` - } - - return this._http.put(`/connection/${connection.id}`, dbCredentials, { - headers: masterKey ? { - masterpwd: masterKey - } : {} - }) - .pipe( - map(res => { - this._masterPassword.checkMasterPassword(connection.masterEncryption, connection.id, masterKey); - this._notifications.showSuccessSnackbar('Connection has been updated successfully.'); - this.connectionsSubject.next(null); - return res; - }), - catchError((err) => { - console.log(err); - const errorMessage = err.error?.message || 'Unknown error'; - const errorDetails = err.error?.originalMessage || ''; - this._notifications.showAlert(AlertType.Error, {abstract: errorMessage, details: errorDetails}, [ - { - type: AlertActionType.Button, - caption: 'Dismiss', - action: (_id: number) => this._notifications.dismissAlert() - } - ]); - // this._notifications.showErrorSnackbar(`${err.error.message}. Connection has not been updated.`); - console.log('updateConnection catchError'); - return throwError(() => new Error(errorMessage)); - } - ) - ); - } - - deleteConnection(id: string, metadata) { - return this._http.put(`/connection/delete/${id}`, metadata) - .pipe( - map(() => { - this.connectionsSubject.next(null); - this._notifications.showSuccessSnackbar('Connection has been deleted successfully.'); - }), - catchError((err) => { - console.log(err); - const errorMessage = err.error?.message || 'Unknown error'; - this._notifications.showErrorSnackbar(errorMessage); - return EMPTY; - } - ) - ); - } - - fetchAuditLog({connectionID, tableName, userEmail, requstedPage, chunkSize}: LogParams) { - if (tableName === "showAll") tableName = null; - if (userEmail === "showAll") userEmail = null; - return this._http.get(`/logs/${connectionID}`, { - params: { - page: requstedPage.toString(), - perPage: chunkSize.toString(), - ...(tableName ? {tableName} : {}), - ...(userEmail ? {email: userEmail} : {}), - } - }) - .pipe( - map(res => res), - catchError((err) => { - console.log(err); - const errorMessage = err.error?.message || 'Unknown error'; - this._notifications.showErrorSnackbar(errorMessage); - return EMPTY; - } - ) - ); - } - - getConnectionSettings(connectionID: string) { - return this._http.get(`/connection/properties/${connectionID}`) - .pipe( - map((res: any) => { - if (res) { - this._themeService.updateColors({ palettes: { primaryPalette: res.primary_color, accentedPalette: res.secondary_color }}); - } - return res; - }), - catchError((err) => { - console.log(err); - const errorMessage = err.error?.message || 'Unknown error'; - this._notifications.showErrorSnackbar(`${errorMessage}.`); - return EMPTY; - } - ) - ); - } - - createConnectionSettings(connectionID: string, settings: ConnectionSettings) { - return this._http.post(`/connection/properties/${connectionID}`, settings) - .pipe( - map(res => { - this._notifications.showSuccessSnackbar('Connection settings has been created successfully.'); - return res; - }), - catchError((err) => { - console.log(err); - const errorMessage = err.error?.message || 'Unknown error'; - this._notifications.showErrorSnackbar(`${errorMessage}.`); - return EMPTY; - } - ) - ); - } - - updateConnectionSettings(connectionID: string, settings: ConnectionSettings) { - return this._http.put(`/connection/properties/${connectionID}`, settings) - .pipe( - map(res => { - this._notifications.showSuccessSnackbar('Connection settings has been updated successfully.'); - return res; - }), - catchError((err) => { - console.log(err); - const errorMessage = err.error?.message || 'Unknown error'; - this._notifications.showErrorSnackbar(`${errorMessage}.`); - return EMPTY; - } - ) - ); - } - - deleteConnectionSettings(connectionID: string) { - return this._http.delete(`/connection/properties/${connectionID}`) - .pipe( - map(() => { - this._notifications.showSuccessSnackbar('Connection settings has been removed successfully.'); - }), - catchError((err) => { - console.log(err); - const errorMessage = err.error?.message || 'Unknown error'; - this._notifications.showErrorSnackbar(`${errorMessage}.`); - return EMPTY; - } - ) - ); - } - - getTablesFolders(connectionID: string) { - return this._http.get(`/table-categories/${connectionID}`) - .pipe( - map(res => { - return res; - }), - catchError((err) => { - console.log(err); - const errorMessage = err.error?.message || 'Unknown error'; - this._notifications.showErrorSnackbar(`${errorMessage}.`); - return EMPTY; - }) - ); - } - - updateTablesFolders(connectionID: string, tablesFolders: any){ - return this._http.put(`/table-categories/${connectionID}`, tablesFolders) - .pipe( - map(res => { - // this._notifications.showSuccessSnackbar('Connection settings has been updated successfully.'); - return res; - }), - catchError((err) => { - console.log(err); - const errorMessage = err.error?.message || 'Unknown error'; - this._notifications.showErrorSnackbar(`${errorMessage}.`); - return EMPTY; - }) - ); - } + }); + } else { + this.connection = { ...this.connectionInitialState }; + this.isCustomAccentedColor = false; + this._themeService.updateColors({ palettes: { primaryPalette: '#212121', accentedPalette: '#C177FC' } }); + } + + console.log('this.defaultDisplayTable'); + console.log(this.defaultDisplayTable); + } + + isPermitted(accessLevel: AccessLevel) { + return accessLevel === 'edit' || accessLevel === 'readonly'; + } + + defineConnectionType(connection) { + if (connection.type?.startsWith('agent_')) { + connection.type = connection.type.slice(6); + connection.connectionType = ConnectionType.Agent; + } else { + connection.connectionType = ConnectionType.Direct; + } + return connection; + } + + defineConnectionTitle(connection: Connection) { + if (!connection.title && connection.masterEncryption) return 'Untitled encrypted connection'; + if (!connection.title && !connection.database) return 'Untitled connection'; + return connection.title || connection.database; + } + + private checkAndSendConversion() { + const now = new Date(); + const firstVisitTime = localStorage.getItem('first_visit_time'); + + if (!firstVisitTime) { + // First visit - record the current date + localStorage.setItem('first_visit_time', now.toISOString()); + return; + } + + const firstVisit = new Date(firstVisitTime); + const daysDifference = Math.floor((now.getTime() - firstVisit.getTime()) / (1000 * 60 * 60 * 24)); + + if (daysDifference >= 7) { + const repeatConversionSent = localStorage.getItem('repeat_conversion_sent'); + + if (!repeatConversionSent) { + localStorage.setItem('repeat_conversion_sent', 'true'); + + // Send conversion event + if (typeof window !== 'undefined' && (window as any).gtag) { + (window as any).gtag('event', 'conversion', { + send_to: 'AW-419937947/jqGyCJWo4qobEJv9nsgB', + value: 1.0, + currency: 'USD', + event_callback: () => { + console.log('Conversion event sent successfully'); + }, + }); + } + } + } + } + + fetchConnections() { + // Check for first visit and send conversion if needed + this.checkAndSendConversion(); + + return this._http.get('/connections').pipe( + map((res) => { + const connections = res.connections.map((connectionItem) => { + const connection = this.defineConnectionType(connectionItem.connection); + const displayTitle = this.defineConnectionTitle(connectionItem.connection); + return { ...connectionItem, connection, displayTitle }; + }); + this.ownConnections = connections.filter((connectionItem) => !connectionItem.connection.isTestConnection); + this.testConnections = connections.filter((connectionItem) => connectionItem.connection.isTestConnection); + return connections; + }), + catchError((err) => { + console.log(err); + const errorMessage = err.error?.message || 'Unknown error'; + const errorDetails = err.error?.originalMessage || ''; + this._notifications.showAlert(AlertType.Error, { abstract: errorMessage, details: errorDetails }, [ + { + type: AlertActionType.Button, + caption: 'Dismiss', + action: (_id: number) => this._notifications.dismissAlert(), + }, + ]); + return EMPTY; + }), + ); + } + + fetchConnection(id: string) { + return this._http.get(`/connection/one/${id}`).pipe( + map((res) => { + const connection = this.defineConnectionType(res.connection); + if (res.connectionProperties) { + this.defaultDisplayTable = res.connectionProperties.default_showing_table; + this._themeService.updateColors({ + palettes: { + primaryPalette: res.connectionProperties.primary_color, + accentedPalette: res.connectionProperties.secondary_color, + }, + }); + } else { + this.defaultDisplayTable = null; + this._themeService.updateColors({ palettes: { primaryPalette: '#212121', accentedPalette: '#C177FC' } }); + } + return { ...res, connection }; + }), + catchError((err) => { + console.log(err); + if (err.error?.type === 'no_master_key' && this.router.url !== '/connections-list') { + this._masterPassword.showMasterPasswordDialog(); + } + const errorMessage = err.error?.message || 'Unknown error'; + this._notifications.showErrorSnackbar(errorMessage); + return EMPTY; + }), + ); + } + + testConnection(connectionID: string, connection: Connection) { + let dbCredentials; + dbCredentials = { + ...connection, + port: parseInt(connection.port, 10), + sshPort: parseInt(connection.sshPort, 10), + }; + + if (connection.connectionType === 'agent') { + dbCredentials.type = `agent_${dbCredentials.type}`; + } + + return this._http + .post(`/connection/test`, dbCredentials, { + params: { + ...(connectionID ? { connectionId: connectionID } : {}), + }, + }) + .pipe( + map((res) => res), + catchError((err) => { + console.log(err); + const errorMessage = err.error?.message || 'Unknown error'; + const errorDetails = err.error?.originalMessage || ''; + this._notifications.showAlert(AlertType.Error, { abstract: errorMessage, details: errorDetails }, []); + return EMPTY; + }), + ); + } + + createConnection(connection: Connection, masterKey: string) { + let dbCredentials; + dbCredentials = { + ...connection, + port: parseInt(connection.port, 10), + sshPort: parseInt(connection.sshPort, 10), + }; + + if (connection.connectionType === 'agent') { + dbCredentials.type = `agent_${dbCredentials.type}`; + } + + return this._http + .post('/connection', dbCredentials, { + headers: masterKey + ? { + masterpwd: masterKey, + } + : {}, + }) + .pipe( + map((res: any) => { + this.connectionsSubject.next(null); + this._masterPassword.checkMasterPassword(connection.masterEncryption, res.id, masterKey); + this._notifications.showSuccessSnackbar('Connection was added successfully.'); + return res; + }), + catchError((err) => { + console.log(err); + const errorMessage = err.error?.message || 'Unknown error'; + const errorDetails = err.error?.originalMessage || ''; + this._notifications.showAlert(AlertType.Error, { abstract: errorMessage, details: errorDetails }, []); + return throwError(() => errorMessage); + }), + ); + } + + updateConnection(connection: Connection, masterKey: string) { + let dbCredentials; + dbCredentials = { + ...connection, + port: parseInt(connection.port, 10), + sshPort: parseInt(connection.sshPort, 10), + }; + + if (connection.connectionType === 'agent') { + dbCredentials.type = `agent_${dbCredentials.type}`; + } + + return this._http + .put(`/connection/${connection.id}`, dbCredentials, { + headers: masterKey + ? { + masterpwd: masterKey, + } + : {}, + }) + .pipe( + map((res) => { + this._masterPassword.checkMasterPassword(connection.masterEncryption, connection.id, masterKey); + this._notifications.showSuccessSnackbar('Connection has been updated successfully.'); + this.connectionsSubject.next(null); + return res; + }), + catchError((err) => { + console.log(err); + const errorMessage = err.error?.message || 'Unknown error'; + const errorDetails = err.error?.originalMessage || ''; + this._notifications.showAlert(AlertType.Error, { abstract: errorMessage, details: errorDetails }, [ + { + type: AlertActionType.Button, + caption: 'Dismiss', + action: (_id: number) => this._notifications.dismissAlert(), + }, + ]); + // this._notifications.showErrorSnackbar(`${err.error.message}. Connection has not been updated.`); + console.log('updateConnection catchError'); + return throwError(() => new Error(errorMessage)); + }), + ); + } + + deleteConnection(id: string, metadata) { + return this._http.put(`/connection/delete/${id}`, metadata).pipe( + map(() => { + this.connectionsSubject.next(null); + this._notifications.showSuccessSnackbar('Connection has been deleted successfully.'); + }), + catchError((err) => { + console.log(err); + const errorMessage = err.error?.message || 'Unknown error'; + this._notifications.showErrorSnackbar(errorMessage); + return EMPTY; + }), + ); + } + + fetchAuditLog({ connectionID, tableName, userEmail, requstedPage, chunkSize }: LogParams) { + if (tableName === 'showAll') tableName = null; + if (userEmail === 'showAll') userEmail = null; + return this._http + .get(`/logs/${connectionID}`, { + params: { + page: requstedPage.toString(), + perPage: chunkSize.toString(), + ...(tableName ? { tableName } : {}), + ...(userEmail ? { email: userEmail } : {}), + }, + }) + .pipe( + map((res) => res), + catchError((err) => { + console.log(err); + const errorMessage = err.error?.message || 'Unknown error'; + this._notifications.showErrorSnackbar(errorMessage); + return EMPTY; + }), + ); + } + + getConnectionSettings(connectionID: string) { + return this._http.get(`/connection/properties/${connectionID}`).pipe( + map((res: any) => { + if (res) { + this._themeService.updateColors({ + palettes: { primaryPalette: res.primary_color, accentedPalette: res.secondary_color }, + }); + } + return res; + }), + catchError((err) => { + console.log(err); + const errorMessage = err.error?.message || 'Unknown error'; + this._notifications.showErrorSnackbar(`${errorMessage}.`); + return EMPTY; + }), + ); + } + + createConnectionSettings(connectionID: string, settings: ConnectionSettings) { + return this._http.post(`/connection/properties/${connectionID}`, settings).pipe( + map((res) => { + this._notifications.showSuccessSnackbar('Connection settings has been created successfully.'); + return res; + }), + catchError((err) => { + console.log(err); + const errorMessage = err.error?.message || 'Unknown error'; + this._notifications.showErrorSnackbar(`${errorMessage}.`); + return EMPTY; + }), + ); + } + + updateConnectionSettings(connectionID: string, settings: ConnectionSettings) { + return this._http.put(`/connection/properties/${connectionID}`, settings).pipe( + map((res) => { + this._notifications.showSuccessSnackbar('Connection settings has been updated successfully.'); + return res; + }), + catchError((err) => { + console.log(err); + const errorMessage = err.error?.message || 'Unknown error'; + this._notifications.showErrorSnackbar(`${errorMessage}.`); + return EMPTY; + }), + ); + } + + deleteConnectionSettings(connectionID: string) { + return this._http.delete(`/connection/properties/${connectionID}`).pipe( + map(() => { + this._notifications.showSuccessSnackbar('Connection settings has been removed successfully.'); + }), + catchError((err) => { + console.log(err); + const errorMessage = err.error?.message || 'Unknown error'; + this._notifications.showErrorSnackbar(`${errorMessage}.`); + return EMPTY; + }), + ); + } + + getTablesFolders(connectionID: string) { + return this._http.get(`/table-categories/${connectionID}`).pipe( + map((res) => { + return res; + }), + catchError((err) => { + console.log(err); + const errorMessage = err.error?.message || 'Unknown error'; + this._notifications.showErrorSnackbar(`${errorMessage}.`); + return EMPTY; + }), + ); + } + + updateTablesFolders(connectionID: string, tablesFolders: any) { + return this._http.put(`/table-categories/${connectionID}`, tablesFolders).pipe( + map((res) => { + // this._notifications.showSuccessSnackbar('Connection settings has been updated successfully.'); + return res; + }), + catchError((err) => { + console.log(err); + const errorMessage = err.error?.message || 'Unknown error'; + this._notifications.showErrorSnackbar(`${errorMessage}.`); + return EMPTY; + }), + ); + } } diff --git a/frontend/src/app/services/saved-queries.service.ts b/frontend/src/app/services/saved-queries.service.ts new file mode 100644 index 000000000..10969d9a3 --- /dev/null +++ b/frontend/src/app/services/saved-queries.service.ts @@ -0,0 +1,137 @@ +import { HttpClient } from '@angular/common/http'; +import { computed, Injectable, inject, signal } from '@angular/core'; +import { rxResource } from '@angular/core/rxjs-interop'; +import { EMPTY, Observable } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; +import { + CreateSavedQueryPayload, + QueryExecutionResult, + SavedQuery, + TestQueryPayload, + TestQueryResult, + UpdateSavedQueryPayload, +} from '../models/saved-query'; +import { NotificationsService } from './notifications.service'; + +export type QueryUpdateEvent = 'created' | 'updated' | 'deleted' | ''; + +@Injectable({ + providedIn: 'root', +}) +export class SavedQueriesService { + private _http = inject(HttpClient); + private _notifications = inject(NotificationsService); + + private _queriesUpdated = signal(''); + public readonly queriesUpdated = this._queriesUpdated.asReadonly(); + + // Active connection for reactive fetching + private _activeConnectionId = signal(null); + + // Resource for saved queries + private _savedQueriesResource = rxResource({ + params: () => this._activeConnectionId(), + stream: ({ params: connectionId }) => { + if (!connectionId) return EMPTY; + return this._http.get(`/connection/${connectionId}/saved-queries`).pipe( + catchError((err) => { + console.log(err); + this._notifications.showErrorSnackbar(err.error?.message || 'Failed to fetch saved queries'); + return EMPTY; + }), + ); + }, + }); + + // Computed signals for convenient access + public readonly savedQueries = computed(() => this._savedQueriesResource.value() ?? []); + public readonly savedQueriesLoading = computed(() => this._savedQueriesResource.isLoading()); + public readonly savedQueriesError = computed(() => this._savedQueriesResource.error() as Error | null); + + // Methods to control resource + setActiveConnection(connectionId: string): void { + this._activeConnectionId.set(connectionId); + } + + refreshSavedQueries(): void { + this._savedQueriesResource.reload(); + } + + fetchSavedQuery(connectionId: string, queryId: string): Observable { + return this._http.get(`/connection/${connectionId}/saved-query/${queryId}`).pipe( + catchError((err) => { + console.log(err); + this._notifications.showErrorSnackbar(err.error?.message || 'Failed to fetch saved query'); + return EMPTY; + }), + ); + } + + createSavedQuery(connectionId: string, payload: CreateSavedQueryPayload): Observable { + return this._http.post(`/connection/${connectionId}/saved-query`, payload).pipe( + tap(() => { + this._notifications.showSuccessSnackbar('Saved query created successfully'); + this._queriesUpdated.set('created'); + }), + catchError((err) => { + console.log(err); + this._notifications.showErrorSnackbar(err.error?.message || 'Failed to create saved query'); + return EMPTY; + }), + ); + } + + updateSavedQuery(connectionId: string, queryId: string, payload: UpdateSavedQueryPayload): Observable { + return this._http.put(`/connection/${connectionId}/saved-query/${queryId}`, payload).pipe( + tap(() => { + this._notifications.showSuccessSnackbar('Saved query updated successfully'); + this._queriesUpdated.set('updated'); + }), + catchError((err) => { + console.log(err); + this._notifications.showErrorSnackbar(err.error?.message || 'Failed to update saved query'); + return EMPTY; + }), + ); + } + + deleteSavedQuery(connectionId: string, queryId: string): Observable { + return this._http.delete(`/connection/${connectionId}/saved-query/${queryId}`).pipe( + tap(() => { + this._notifications.showSuccessSnackbar('Saved query deleted successfully'); + this._queriesUpdated.set('deleted'); + }), + catchError((err) => { + console.log(err); + this._notifications.showErrorSnackbar(err.error?.message || 'Failed to delete saved query'); + return EMPTY; + }), + ); + } + + executeSavedQuery(connectionId: string, queryId: string, tableName?: string): Observable { + const params: Record = {}; + if (tableName) { + params['tableName'] = tableName; + } + return this._http + .post(`/connection/${connectionId}/saved-query/${queryId}/execute`, {}, { params }) + .pipe( + catchError((err) => { + console.log(err); + this._notifications.showErrorSnackbar(err.error?.message || 'Failed to execute query'); + return EMPTY; + }), + ); + } + + testQuery(connectionId: string, payload: TestQueryPayload): Observable { + return this._http.post(`/connection/${connectionId}/query/test`, payload).pipe( + catchError((err) => { + console.log(err); + this._notifications.showErrorSnackbar(err.error?.message || 'Failed to test query'); + return EMPTY; + }), + ); + } +} diff --git a/frontend/src/main.ts b/frontend/src/main.ts index 81950ef16..d076afee3 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -12,6 +12,7 @@ import * as Sentry from '@sentry/angular'; import { Angulartics2Module } from 'angulartics2'; import { DynamicModule } from 'ng-dynamic-component'; import { SignalComponentIoModule } from 'ng-dynamic-component/signal-component-io'; +import { provideCharts, withDefaultRegisterables } from 'ng2-charts'; import { CookieService } from 'ngx-cookie-service'; import { MarkdownModule, provideMarkdown } from 'ngx-markdown'; import { NgxStripeModule } from 'ngx-stripe'; @@ -140,5 +141,6 @@ bootstrapApplication(AppComponent, { ...saasExtraProviders, provideHttpClient(withInterceptorsFromDi()), provideAnimations(), + provideCharts(withDefaultRegisterables()), ], }).catch((err) => console.error(err)); diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 843472ae7..8ffe1362c 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -166,28 +166,10 @@ __metadata: languageName: node linkType: hard -"@alloc/quick-lru@npm:^5.2.0": - version: 5.2.0 - resolution: "@alloc/quick-lru@npm:5.2.0" - checksum: bdc35758b552bcf045733ac047fb7f9a07c4678b944c641adfbd41f798b4b91fffd0fdc0df2578d9b0afc7b4d636aa6e110ead5d6281a2adc1ab90efd7f057f8 - languageName: node - linkType: hard - "@amplitude/analytics-connector@npm:^1.4.6": - version: 1.6.2 - resolution: "@amplitude/analytics-connector@npm:1.6.2" - dependencies: - "@amplitude/experiment-core": ^0.10.1 - checksum: 31451926a4b5d6ae3779113d0bcfd72d2470b69d3a72e25111b4b844a8410abde2b5d819f02226375edcf0ba9ab98893b7d6cae9a8a223a3c8e03d7441a4b7ab - languageName: node - linkType: hard - -"@amplitude/experiment-core@npm:^0.10.1": - version: 0.10.1 - resolution: "@amplitude/experiment-core@npm:0.10.1" - dependencies: - js-base64: ^3.7.5 - checksum: 156bc59f7fdd8baf4f496629be02a34d00d3dd1f8f989b613dfab8a325cc6eb5c0c4ae58d45c8615cdf94dacf16fe58151a28566d79f5adf944188c770fe2c12 + version: 1.6.4 + resolution: "@amplitude/analytics-connector@npm:1.6.4" + checksum: 2651e296c39a0fee687e7ce4315e671ed52aab513a00ea00fd45d8199c3cda945da1a23d37de255926830a268a4135bd31a16fb45118ebdbda58615b48037005 languageName: node linkType: hard @@ -235,15 +217,25 @@ __metadata: languageName: node linkType: hard +"@angular-devkit/architect@npm:0.2003.15": + version: 0.2003.15 + resolution: "@angular-devkit/architect@npm:0.2003.15" + dependencies: + "@angular-devkit/core": 20.3.15 + rxjs: 7.8.2 + checksum: 22482451611ee11f4c50838439ce6e28d3aea3a7c8418e03ede199e6029e3c7c5df20c3cb8a01723f63710ffc8dad3690b59211bd09d58673aa375e6e24f034c + languageName: node + linkType: hard + "@angular-devkit/build-angular@npm:20": - version: 20.3.14 - resolution: "@angular-devkit/build-angular@npm:20.3.14" + version: 20.3.15 + resolution: "@angular-devkit/build-angular@npm:20.3.15" dependencies: "@ampproject/remapping": 2.3.0 - "@angular-devkit/architect": 0.2003.14 - "@angular-devkit/build-webpack": 0.2003.14 - "@angular-devkit/core": 20.3.14 - "@angular/build": 20.3.14 + "@angular-devkit/architect": 0.2003.15 + "@angular-devkit/build-webpack": 0.2003.15 + "@angular-devkit/core": 20.3.15 + "@angular/build": 20.3.15 "@babel/core": 7.28.3 "@babel/generator": 7.28.3 "@babel/helper-annotate-as-pure": 7.27.3 @@ -254,7 +246,7 @@ __metadata: "@babel/preset-env": 7.28.3 "@babel/runtime": 7.28.3 "@discoveryjs/json-ext": 0.6.3 - "@ngtools/webpack": 20.3.14 + "@ngtools/webpack": 20.3.15 ansi-colors: 4.1.3 autoprefixer: 10.4.21 babel-loader: 10.0.0 @@ -289,7 +281,7 @@ __metadata: terser: 5.43.1 tree-kill: 1.2.2 tslib: 2.8.1 - webpack: 5.101.2 + webpack: 5.104.1 webpack-dev-middleware: 7.4.2 webpack-dev-server: 5.2.2 webpack-merge: 6.0.1 @@ -301,7 +293,7 @@ __metadata: "@angular/platform-browser": ^20.0.0 "@angular/platform-server": ^20.0.0 "@angular/service-worker": ^20.0.0 - "@angular/ssr": ^20.3.14 + "@angular/ssr": ^20.3.15 "@web/test-runner": ^0.20.0 browser-sync: ^3.0.2 jest: ^29.5.0 || ^30.2.0 @@ -343,20 +335,20 @@ __metadata: optional: true tailwindcss: optional: true - checksum: c8f44b5d3dcabecb948ad7d8200e47305108bfe6fcb2cb8f1fda2796f47a1739984ce29f9782be97c5a35d040cdc38d4133a8a08255242a5f03e8aebfd14401a + checksum: 93c07434b369be6e29de78cd30e317ab9dab22afff76be707448c7b6d00fb488a5ab0ac65b0252f1bc49ce5642b222d1ce1b136b2645fba39abb70731a0ee669 languageName: node linkType: hard -"@angular-devkit/build-webpack@npm:0.2003.14": - version: 0.2003.14 - resolution: "@angular-devkit/build-webpack@npm:0.2003.14" +"@angular-devkit/build-webpack@npm:0.2003.15": + version: 0.2003.15 + resolution: "@angular-devkit/build-webpack@npm:0.2003.15" dependencies: - "@angular-devkit/architect": 0.2003.14 + "@angular-devkit/architect": 0.2003.15 rxjs: 7.8.2 peerDependencies: webpack: ^5.30.0 webpack-dev-server: ^5.0.2 - checksum: 85c03f1719f4c371012c1b8df8b2e5cbc1d375a7ca5b8caf9d38a8433c61d1c2f84ab237ff89341377be767e94e636b96141c59e1308414037135ed705034628 + checksum: a69690ca69912c4891aa31b42117031b8ce25f411814865948d8e1d61446c774a839cd34bf52109ac13f96166ac25a235c20a9c30747ff82117b5d5301de5028 languageName: node linkType: hard @@ -379,16 +371,35 @@ __metadata: languageName: node linkType: hard -"@angular-devkit/schematics@npm:20.3.14": - version: 20.3.14 - resolution: "@angular-devkit/schematics@npm:20.3.14" +"@angular-devkit/core@npm:20.3.15": + version: 20.3.15 + resolution: "@angular-devkit/core@npm:20.3.15" dependencies: - "@angular-devkit/core": 20.3.14 + ajv: 8.17.1 + ajv-formats: 3.0.1 + jsonc-parser: 3.3.1 + picomatch: 4.0.3 + rxjs: 7.8.2 + source-map: 0.7.6 + peerDependencies: + chokidar: ^4.0.0 + peerDependenciesMeta: + chokidar: + optional: true + checksum: fab0b32a1c34e59b879d712b71cabae2aa9c5562c41750696a90a99dd9626b6482103bc74c5f3c8be6c05008a826525a755fe70c95679b010d6f7c29e6b39930 + languageName: node + linkType: hard + +"@angular-devkit/schematics@npm:20.3.15": + version: 20.3.15 + resolution: "@angular-devkit/schematics@npm:20.3.15" + dependencies: + "@angular-devkit/core": 20.3.15 jsonc-parser: 3.3.1 magic-string: 0.30.17 ora: 8.2.0 rxjs: 7.8.2 - checksum: fc662ae29f3bd82e5be4beef4ecbf74767bbbfb624d85df11b6e6078d3df82a4857ed89a0210bf38a084343cd6efb6be0ebb8684d9a92f6249649bde94a00cd3 + checksum: c8ced62c43e5976e88cfd9328204b5d8a0607a2631036850e9403d7e1b398cfa573dbf3b9ed8fe834bbdf8d13d439514a77b05a2b7b6cbad4c1a7427734bec37 languageName: node linkType: hard @@ -483,6 +494,86 @@ __metadata: languageName: node linkType: hard +"@angular/build@npm:20.3.15": + version: 20.3.15 + resolution: "@angular/build@npm:20.3.15" + dependencies: + "@ampproject/remapping": 2.3.0 + "@angular-devkit/architect": 0.2003.15 + "@babel/core": 7.28.3 + "@babel/helper-annotate-as-pure": 7.27.3 + "@babel/helper-split-export-declaration": 7.24.7 + "@inquirer/confirm": 5.1.14 + "@vitejs/plugin-basic-ssl": 2.1.0 + beasties: 0.3.5 + browserslist: ^4.23.0 + esbuild: 0.25.9 + https-proxy-agent: 7.0.6 + istanbul-lib-instrument: 6.0.3 + jsonc-parser: 3.3.1 + listr2: 9.0.1 + lmdb: 3.4.2 + magic-string: 0.30.17 + mrmime: 2.0.1 + parse5-html-rewriting-stream: 8.0.0 + picomatch: 4.0.3 + piscina: 5.1.3 + rollup: 4.52.3 + sass: 1.90.0 + semver: 7.7.2 + source-map-support: 0.5.21 + tinyglobby: 0.2.14 + vite: 7.1.11 + watchpack: 2.4.4 + peerDependencies: + "@angular/compiler": ^20.0.0 + "@angular/compiler-cli": ^20.0.0 + "@angular/core": ^20.0.0 + "@angular/localize": ^20.0.0 + "@angular/platform-browser": ^20.0.0 + "@angular/platform-server": ^20.0.0 + "@angular/service-worker": ^20.0.0 + "@angular/ssr": ^20.3.15 + karma: ^6.4.0 + less: ^4.2.0 + ng-packagr: ^20.0.0 + postcss: ^8.4.0 + tailwindcss: ^2.0.0 || ^3.0.0 || ^4.0.0 + tslib: ^2.3.0 + typescript: ">=5.8 <6.0" + vitest: ^3.1.1 + dependenciesMeta: + lmdb: + optional: true + peerDependenciesMeta: + "@angular/core": + optional: true + "@angular/localize": + optional: true + "@angular/platform-browser": + optional: true + "@angular/platform-server": + optional: true + "@angular/service-worker": + optional: true + "@angular/ssr": + optional: true + karma: + optional: true + less: + optional: true + ng-packagr: + optional: true + postcss: + optional: true + tailwindcss: + optional: true + vitest: + optional: true + checksum: 82dd976e2f9f69bedb51315619dafc2b0a52fb897af0b56a03533514be9d6f509cded2d94f83e300711f3e4f65d88eb09f69fb55214f92359fdd44b76109c524 + languageName: node + linkType: hard + "@angular/cdk@npm:~20.2.14": version: 20.2.14 resolution: "@angular/cdk@npm:20.2.14" @@ -498,30 +589,30 @@ __metadata: linkType: hard "@angular/cli@npm:~20.3.14": - version: 20.3.14 - resolution: "@angular/cli@npm:20.3.14" + version: 20.3.15 + resolution: "@angular/cli@npm:20.3.15" dependencies: - "@angular-devkit/architect": 0.2003.14 - "@angular-devkit/core": 20.3.14 - "@angular-devkit/schematics": 20.3.14 + "@angular-devkit/architect": 0.2003.15 + "@angular-devkit/core": 20.3.15 + "@angular-devkit/schematics": 20.3.15 "@inquirer/prompts": 7.8.2 "@listr2/prompt-adapter-inquirer": 3.0.1 "@modelcontextprotocol/sdk": 1.25.2 - "@schematics/angular": 20.3.14 + "@schematics/angular": 20.3.15 "@yarnpkg/lockfile": 1.1.0 algoliasearch: 5.35.0 ini: 5.0.0 jsonc-parser: 3.3.1 listr2: 9.0.1 npm-package-arg: 13.0.0 - pacote: 21.0.0 + pacote: 21.0.4 resolve: 1.22.10 semver: 7.7.2 yargs: 18.0.0 zod: 4.1.13 bin: ng: bin/ng.js - checksum: e716fda10b3fa06556c69f5566e2e09616694ff2b5012572aa5b08a0d3339be67a8f8a9a3dec84f4d85fa20365a349e561416df734d1a61fb0dc7c30785f22cb + checksum: 12a7e1a83fbaaeeeaad39f4354c341cf978445cc902785dbd040b7bdaaa42de71a4e8e54db6ee0f5f73554b448a9ea0c2734551c0079bb615f6a53d014bd56ac languageName: node linkType: hard @@ -611,19 +702,18 @@ __metadata: linkType: hard "@angular/material@npm:>12.0.0": - version: 19.0.3 - resolution: "@angular/material@npm:19.0.3" + version: 21.1.2 + resolution: "@angular/material@npm:21.1.2" dependencies: tslib: ^2.3.0 peerDependencies: - "@angular/animations": ^19.0.0 || ^20.0.0 - "@angular/cdk": 19.0.3 - "@angular/common": ^19.0.0 || ^20.0.0 - "@angular/core": ^19.0.0 || ^20.0.0 - "@angular/forms": ^19.0.0 || ^20.0.0 - "@angular/platform-browser": ^19.0.0 || ^20.0.0 + "@angular/cdk": 21.1.2 + "@angular/common": ^21.0.0 || ^22.0.0 + "@angular/core": ^21.0.0 || ^22.0.0 + "@angular/forms": ^21.0.0 || ^22.0.0 + "@angular/platform-browser": ^21.0.0 || ^22.0.0 rxjs: ^6.5.3 || ^7.4.0 - checksum: 268dc5185d4312b08f24e5f1d294eaceb80afa974a9a222f35217f06ca4840cc3a183b1b4155134ffbf27950c595a5f79b15d2a39ea34fa239f7a28cf8372e68 + checksum: 70a965bab0fc747f4c59528b3f7ba6b04a977dc96840436fce7078ac2bf893a2442c29a2d705f2cb84cc89d99f605828759f24eb64666ac385ecf0cd1f249909 languageName: node linkType: hard @@ -697,13 +787,6 @@ __metadata: languageName: node linkType: hard -"@antfu/utils@npm:^9.2.0": - version: 9.3.0 - resolution: "@antfu/utils@npm:9.3.0" - checksum: 7893a291971f8bf3ffd0d428077fdea3129ba849baf66b9d2f397b9d36f0554dbc12fa484ce8891d747107efe1bc9de29a24309f2194ea685fc0c69e133400d9 - languageName: node - linkType: hard - "@asamuzakjp/css-color@npm:^4.1.1": version: 4.1.1 resolution: "@asamuzakjp/css-color@npm:4.1.1" @@ -718,15 +801,15 @@ __metadata: linkType: hard "@asamuzakjp/dom-selector@npm:^6.7.6": - version: 6.7.6 - resolution: "@asamuzakjp/dom-selector@npm:6.7.6" + version: 6.7.7 + resolution: "@asamuzakjp/dom-selector@npm:6.7.7" dependencies: "@asamuzakjp/nwsapi": ^2.3.9 bidi-js: ^1.0.3 css-tree: ^3.1.0 is-potential-custom-element-name: ^1.0.1 - lru-cache: ^11.2.4 - checksum: fb47d93d06afffe93a166739a7b3d40b36a311b46d215716bf7b60d59462602dffca5eb1b9ae40cdf3bccc6f4e244b525c6c5328f3f7509c39518c0409a9500c + lru-cache: ^11.2.5 + checksum: 73c5ae7ca5899d32b33c5733eba39b0dedcfa3f0fce1f83b6fb4336912a6765f97bddb780b9468556987404c98dce3e0532c14f6fb5b170421e01c73d9ef952c languageName: node linkType: hard @@ -737,50 +820,21 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0, @babel/code-frame@npm:^7.26.2": - version: 7.26.2 - resolution: "@babel/code-frame@npm:7.26.2" - dependencies: - "@babel/helper-validator-identifier": ^7.25.9 - js-tokens: ^4.0.0 - picocolors: ^1.0.0 - checksum: db13f5c42d54b76c1480916485e6900748bbcb0014a8aca87f50a091f70ff4e0d0a6db63cade75eb41fcc3d2b6ba0a7f89e343def4f96f00269b41b8ab8dd7b8 - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/code-frame@npm:7.28.6" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.27.1, @babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/code-frame@npm:7.29.0" dependencies: "@babel/helper-validator-identifier": ^7.28.5 js-tokens: ^4.0.0 picocolors: ^1.1.1 - checksum: 6e98e47fd324b41c1919ff6d0fbf6fa5e991e5beff6b55803d9adaff9e11f4bc432803e52165f7b0d49af0f718209c3138a9b2fd51ff624b19d47704f11f8287 + checksum: 39f5b303757e4d63bbff8133e251094cd4f952b46e3fa9febc7368d907583911d6a1eded6090876dc1feeff5cf6e134fb19b706f8d58d26c5402cd50e5e1aeb2 languageName: node linkType: hard -"@babel/code-frame@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/code-frame@npm:7.27.1" - dependencies: - "@babel/helper-validator-identifier": ^7.27.1 - js-tokens: ^4.0.0 - picocolors: ^1.1.1 - checksum: 5874edc5d37406c4a0bb14cf79c8e51ad412fb0423d176775ac14fc0259831be1bf95bdda9c2aa651126990505e09a9f0ed85deaa99893bc316d2682c5115bdc - languageName: node - linkType: hard - -"@babel/compat-data@npm:^7.25.9": - version: 7.26.3 - resolution: "@babel/compat-data@npm:7.26.3" - checksum: 85c5a9fb365231688c7faeb977f1d659da1c039e17b416f8ef11733f7aebe11fe330dce20c1844cacf243766c1d643d011df1d13cac9eda36c46c6c475693d21 - languageName: node - linkType: hard - -"@babel/compat-data@npm:^7.27.7, @babel/compat-data@npm:^7.28.0, @babel/compat-data@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/compat-data@npm:7.28.6" - checksum: 599b316aa0e3981aa9165ac34609ef5f29ebf5cecc04784e8b4932dd355aaa3599eaa222ff46a2fcfff52f083b8fd212650a52d8af57c4c217c81a100fefba09 +"@babel/compat-data@npm:^7.28.0, @babel/compat-data@npm:^7.28.6": + version: 7.29.0 + resolution: "@babel/compat-data@npm:7.29.0" + checksum: ad19db279dfd06cbe91b505d03be00d603c6d3fcc141cfc14f4ace5c558193e9b6aae4788cb01fd209c4c850e52d73c8f3c247680e3c0d84fa17ab8b3d50c808 languageName: node linkType: hard @@ -808,25 +862,25 @@ __metadata: linkType: hard "@babel/core@npm:^7.23.9": - version: 7.26.0 - resolution: "@babel/core@npm:7.26.0" + version: 7.29.0 + resolution: "@babel/core@npm:7.29.0" dependencies: - "@ampproject/remapping": ^2.2.0 - "@babel/code-frame": ^7.26.0 - "@babel/generator": ^7.26.0 - "@babel/helper-compilation-targets": ^7.25.9 - "@babel/helper-module-transforms": ^7.26.0 - "@babel/helpers": ^7.26.0 - "@babel/parser": ^7.26.0 - "@babel/template": ^7.25.9 - "@babel/traverse": ^7.25.9 - "@babel/types": ^7.26.0 + "@babel/code-frame": ^7.29.0 + "@babel/generator": ^7.29.0 + "@babel/helper-compilation-targets": ^7.28.6 + "@babel/helper-module-transforms": ^7.28.6 + "@babel/helpers": ^7.28.6 + "@babel/parser": ^7.29.0 + "@babel/template": ^7.28.6 + "@babel/traverse": ^7.29.0 + "@babel/types": ^7.29.0 + "@jridgewell/remapping": ^2.3.5 convert-source-map: ^2.0.0 debug: ^4.1.0 gensync: ^1.0.0-beta.2 json5: ^2.2.3 semver: ^6.3.1 - checksum: b296084cfd818bed8079526af93b5dfa0ba70282532d2132caf71d4060ab190ba26d3184832a45accd82c3c54016985a4109ab9118674347a7e5e9bc464894e6 + checksum: 85e1df6e213382c46dee27bcd07ed9202fa108a85bb74eb37be656308fd949349171ad2aa17cc84cf0720c908dc9ea6309d25e64d2a7fcdaa63721ce0c67c10b languageName: node linkType: hard @@ -843,42 +897,16 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.26.0, @babel/generator@npm:^7.26.3": - version: 7.26.3 - resolution: "@babel/generator@npm:7.26.3" - dependencies: - "@babel/parser": ^7.26.3 - "@babel/types": ^7.26.3 - "@jridgewell/gen-mapping": ^0.3.5 - "@jridgewell/trace-mapping": ^0.3.25 - jsesc: ^3.0.2 - checksum: fb09fa55c66f272badf71c20a3a2cee0fa1a447fed32d1b84f16a668a42aff3e5f5ddc6ed5d832dda1e952187c002ca1a5cdd827022efe591b6ac44cada884ea - languageName: node - linkType: hard - -"@babel/generator@npm:^7.28.0": - version: 7.28.0 - resolution: "@babel/generator@npm:7.28.0" - dependencies: - "@babel/parser": ^7.28.0 - "@babel/types": ^7.28.0 - "@jridgewell/gen-mapping": ^0.3.12 - "@jridgewell/trace-mapping": ^0.3.28 - jsesc: ^3.0.2 - checksum: 3fc9ecca7e7a617cf7b7357e11975ddfaba4261f374ab915f5d9f3b1ddc8fd58da9f39492396416eb08cf61972d1aa13c92d4cca206533c553d8651c2740f07f - languageName: node - linkType: hard - -"@babel/generator@npm:^7.28.3, @babel/generator@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/generator@npm:7.28.6" +"@babel/generator@npm:^7.28.3, @babel/generator@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/generator@npm:7.29.0" dependencies: - "@babel/parser": ^7.28.6 - "@babel/types": ^7.28.6 + "@babel/parser": ^7.29.0 + "@babel/types": ^7.29.0 "@jridgewell/gen-mapping": ^0.3.12 "@jridgewell/trace-mapping": ^0.3.28 jsesc: ^3.0.2 - checksum: 74f62f140e301c8c21652f7db3bc275008708272c0395f178ba6953297af50c4ea484874a44b3f292d242ce8a977fd3f31d9d3a3501c3aaca9cd46e3b1cded01 + checksum: 7d338a9278a401764605fac87f3e223c70b50be15ebd6cf856249db9554133a620cf841ff62e4dfcc46ca59f2c16b62a2ce12891d48e47ed987f19bfbfd5469e languageName: node linkType: hard @@ -891,28 +919,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-annotate-as-pure@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-annotate-as-pure@npm:7.25.9" - dependencies: - "@babel/types": ^7.25.9 - checksum: 41edda10df1ae106a9b4fe617bf7c6df77db992992afd46192534f5cff29f9e49a303231733782dd65c5f9409714a529f215325569f14282046e9d3b7a1ffb6c - languageName: node - linkType: hard - -"@babel/helper-compilation-targets@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-compilation-targets@npm:7.25.9" - dependencies: - "@babel/compat-data": ^7.25.9 - "@babel/helper-validator-option": ^7.25.9 - browserslist: ^4.24.0 - lru-cache: ^5.1.1 - semver: ^6.3.1 - checksum: 3af536e2db358b38f968abdf7d512d425d1018fef2f485d6f131a57a7bcaed32c606b4e148bb230e1508fa42b5b2ac281855a68eb78270f54698c48a83201b9b - languageName: node - linkType: hard - "@babel/helper-compilation-targets@npm:^7.27.1, @babel/helper-compilation-targets@npm:^7.27.2, @babel/helper-compilation-targets@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-compilation-targets@npm:7.28.6" @@ -943,20 +949,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-regexp-features-plugin@npm:^7.18.6": - version: 7.26.3 - resolution: "@babel/helper-create-regexp-features-plugin@npm:7.26.3" - dependencies: - "@babel/helper-annotate-as-pure": ^7.25.9 - regexpu-core: ^6.2.0 - semver: ^6.3.1 - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 50a27d8ce6da5c2fa0c62c132c4d27cfeb36e3233ff1e5220d643de3dafe49423b507382f0b72a696fce7486014b134c1e742f55438590f9405d26765b009af0 - languageName: node - linkType: hard - -"@babel/helper-create-regexp-features-plugin@npm:^7.27.1, @babel/helper-create-regexp-features-plugin@npm:^7.28.5": +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.27.1, @babel/helper-create-regexp-features-plugin@npm:^7.28.5": version: 7.28.5 resolution: "@babel/helper-create-regexp-features-plugin@npm:7.28.5" dependencies: @@ -969,18 +962,18 @@ __metadata: languageName: node linkType: hard -"@babel/helper-define-polyfill-provider@npm:^0.6.5": - version: 0.6.5 - resolution: "@babel/helper-define-polyfill-provider@npm:0.6.5" +"@babel/helper-define-polyfill-provider@npm:^0.6.5, @babel/helper-define-polyfill-provider@npm:^0.6.6": + version: 0.6.6 + resolution: "@babel/helper-define-polyfill-provider@npm:0.6.6" dependencies: - "@babel/helper-compilation-targets": ^7.27.2 - "@babel/helper-plugin-utils": ^7.27.1 - debug: ^4.4.1 + "@babel/helper-compilation-targets": ^7.28.6 + "@babel/helper-plugin-utils": ^7.28.6 + debug: ^4.4.3 lodash.debounce: ^4.0.8 - resolve: ^1.22.10 + resolve: ^1.22.11 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 9fd3b09b209c8ed0d3d8bc1f494f1368b9e1f6e46195af4ce948630fe97d7dafde4882eedace270b319bf6555ddf35e220c77505f6d634f621766cdccbba0aae + checksum: 582efe522e7ef75228f7eeea63fd659567ce865365e3d4b9d94451825114a7f1c8b61791bbbf134aa1b2aa6ee37620b145e74879dace7568107057180153e72e languageName: node linkType: hard @@ -1001,27 +994,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-module-imports@npm:7.25.9" - dependencies: - "@babel/traverse": ^7.25.9 - "@babel/types": ^7.25.9 - checksum: 1b411ce4ca825422ef7065dffae7d8acef52023e51ad096351e3e2c05837e9bf9fca2af9ca7f28dc26d596a588863d0fedd40711a88e350b736c619a80e704e6 - languageName: node - linkType: hard - -"@babel/helper-module-imports@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-module-imports@npm:7.27.1" - dependencies: - "@babel/traverse": ^7.27.1 - "@babel/types": ^7.27.1 - checksum: 92d01c71c0e4aacdc2babce418a9a1a27a8f7d770a210ffa0f3933f321befab18b655bc1241bebc40767516731de0b85639140c42e45a8210abe1e792f115b28 - languageName: node - linkType: hard - -"@babel/helper-module-imports@npm:^7.28.6": +"@babel/helper-module-imports@npm:^7.27.1, @babel/helper-module-imports@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-module-imports@npm:7.28.6" dependencies: @@ -1031,33 +1004,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.26.0": - version: 7.26.0 - resolution: "@babel/helper-module-transforms@npm:7.26.0" - dependencies: - "@babel/helper-module-imports": ^7.25.9 - "@babel/helper-validator-identifier": ^7.25.9 - "@babel/traverse": ^7.25.9 - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 942eee3adf2b387443c247a2c190c17c4fd45ba92a23087abab4c804f40541790d51ad5277e4b5b1ed8d5ba5b62de73857446b7742f835c18ebd350384e63917 - languageName: node - linkType: hard - -"@babel/helper-module-transforms@npm:^7.27.1": - version: 7.27.3 - resolution: "@babel/helper-module-transforms@npm:7.27.3" - dependencies: - "@babel/helper-module-imports": ^7.27.1 - "@babel/helper-validator-identifier": ^7.27.1 - "@babel/traverse": ^7.27.3 - peerDependencies: - "@babel/core": ^7.0.0 - checksum: c611d42d3cb7ba23b1a864fcf8d6cde0dc99e876ca1c9a67e4d7919a70706ded4aaa45420de2bf7f7ea171e078e59f0edcfa15a56d74b9485e151b95b93b946e - languageName: node - linkType: hard - -"@babel/helper-module-transforms@npm:^7.28.3, @babel/helper-module-transforms@npm:^7.28.6": +"@babel/helper-module-transforms@npm:^7.27.1, @babel/helper-module-transforms@npm:^7.28.3, @babel/helper-module-transforms@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-module-transforms@npm:7.28.6" dependencies: @@ -1079,21 +1026,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.18.6": - version: 7.25.9 - resolution: "@babel/helper-plugin-utils@npm:7.25.9" - checksum: e19ec8acf0b696756e6d84531f532c5fe508dce57aa68c75572a77798bd04587a844a9a6c8ea7d62d673e21fdc174d091c9097fb29aea1c1b49f9c6eaa80f022 - languageName: node - linkType: hard - -"@babel/helper-plugin-utils@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-plugin-utils@npm:7.27.1" - checksum: 5d715055301badab62bdb2336075a77f8dc8bd290cad2bc1b37ea3bf1b3efc40594d308082229f239deb4d6b5b80b0a73bce000e595ea74416e0339c11037047 - languageName: node - linkType: hard - -"@babel/helper-plugin-utils@npm:^7.28.6": +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.27.1, @babel/helper-plugin-utils@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-plugin-utils@npm:7.28.6" checksum: a0b4caab5e2180b215faa4d141ceac9e82fad9d446b8023eaeb8d82a6e62024726675b07fe8e616dd12f34e2bb59747e8d57aa8adab3e0717d1b8d691b118379 @@ -1145,13 +1078,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-string-parser@npm:7.25.9" - checksum: 6435ee0849e101681c1849868278b5aee82686ba2c1e27280e5e8aca6233af6810d39f8e4e693d2f2a44a3728a6ccfd66f72d71826a94105b86b731697cdfa99 - languageName: node - linkType: hard - "@babel/helper-string-parser@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-string-parser@npm:7.27.1" @@ -1159,20 +1085,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-validator-identifier@npm:7.25.9" - checksum: 5b85918cb1a92a7f3f508ea02699e8d2422fe17ea8e82acd445006c0ef7520fbf48e3dbcdaf7b0a1d571fc3a2715a29719e5226636cb6042e15fe6ed2a590944 - languageName: node - linkType: hard - -"@babel/helper-validator-identifier@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-validator-identifier@npm:7.27.1" - checksum: 3c7e8391e59d6c85baeefe9afb86432f2ab821c6232b00ea9082a51d3e7e95a2f3fb083d74dc1f49ac82cf238e1d2295dafcb001f7b0fab479f3f56af5eaaa47 - languageName: node - linkType: hard - "@babel/helper-validator-identifier@npm:^7.28.5": version: 7.28.5 resolution: "@babel/helper-validator-identifier@npm:7.28.5" @@ -1180,13 +1092,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-validator-option@npm:7.25.9" - checksum: 9491b2755948ebbdd68f87da907283698e663b5af2d2b1b02a2765761974b1120d5d8d49e9175b167f16f72748ffceec8c9cf62acfbee73f4904507b246e2b3d - languageName: node - linkType: hard - "@babel/helper-validator-option@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-validator-option@npm:7.27.1" @@ -1195,27 +1100,17 @@ __metadata: linkType: hard "@babel/helper-wrap-function@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-wrap-function@npm:7.27.1" - dependencies: - "@babel/template": ^7.27.1 - "@babel/traverse": ^7.27.1 - "@babel/types": ^7.27.1 - checksum: b0427765766494cb5455a188d4cdef5e6167f2835a8ed76f3c25fa3bbe2ec2a716588fa326c52fab0d184a9537200d76e48656e516580a914129d74528322821 - languageName: node - linkType: hard - -"@babel/helpers@npm:^7.26.0": - version: 7.28.2 - resolution: "@babel/helpers@npm:7.28.2" + version: 7.28.6 + resolution: "@babel/helper-wrap-function@npm:7.28.6" dependencies: - "@babel/template": ^7.27.2 - "@babel/types": ^7.28.2 - checksum: 7ead856041f73496eeeb4f7f88a741067c8022fc764cbca7fc3e96ae73ce71969f75fd79b40b2c6a60ca4923f9d56f7798fb86ac2538f13b6d4acb54ebb563a7 + "@babel/template": ^7.28.6 + "@babel/traverse": ^7.28.6 + "@babel/types": ^7.28.6 + checksum: 1281f45d55ff291711de7cf05b8132fc28b8d2b30c6c9cf8fce68669bbe318503ed485057d434efa1a4f91ab55d62bf8f3ecb0a889a9f81d357ad4614cd0fa6c languageName: node linkType: hard -"@babel/helpers@npm:^7.28.3": +"@babel/helpers@npm:^7.28.3, @babel/helpers@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helpers@npm:7.28.6" dependencies: @@ -1225,36 +1120,14 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.23.9, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0, @babel/parser@npm:^7.26.3": - version: 7.26.3 - resolution: "@babel/parser@npm:7.26.3" +"@babel/parser@npm:^7.23.9, @babel/parser@npm:^7.28.3, @babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/parser@npm:7.29.0" dependencies: - "@babel/types": ^7.26.3 + "@babel/types": ^7.29.0 bin: parser: ./bin/babel-parser.js - checksum: e2bff2e9fa6540ee18fecc058bc74837eda2ddcecbe13454667314a93fc0ba26c1fb862c812d84f6d5f225c3bd8d191c3a42d4296e287a882c4e1f82ff2815ff - languageName: node - linkType: hard - -"@babel/parser@npm:^7.27.2, @babel/parser@npm:^7.28.0": - version: 7.28.0 - resolution: "@babel/parser@npm:7.28.0" - dependencies: - "@babel/types": ^7.28.0 - bin: - parser: ./bin/babel-parser.js - checksum: 718e4ce9b0914701d6f74af610d3e7d52b355ef1dcf34a7dedc5930e96579e387f04f96187e308e601828b900b8e4e66d2fe85023beba2ac46587023c45b01cf - languageName: node - linkType: hard - -"@babel/parser@npm:^7.28.3, @babel/parser@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/parser@npm:7.28.6" - dependencies: - "@babel/types": ^7.28.6 - bin: - parser: ./bin/babel-parser.js - checksum: 2a35319792ceef9bc918f0ff854449bef0120707798fe147ef988b0606de226e2fbc3a562ba687148bfe5336c6c67358fb27e71a94e425b28482dcaf0b172fd6 + checksum: b4a1bd3cf46712e439286db9a4105dfa741b5a7720fa1f38f33719cf4f1da9df9fc5b6686128890bd6a62debba287d8d472af153dd629fd4a0a44fe55413cd68 languageName: node linkType: hard @@ -1385,15 +1258,15 @@ __metadata: linkType: hard "@babel/plugin-transform-async-generator-functions@npm:^7.28.0": - version: 7.28.6 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.28.6" + version: 7.29.0 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.29.0" dependencies: "@babel/helper-plugin-utils": ^7.28.6 "@babel/helper-remap-async-to-generator": ^7.27.1 - "@babel/traverse": ^7.28.6 + "@babel/traverse": ^7.29.0 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 0c9e362039c7b0d6620845021b8f576908063a4bfd5857feba59d6097204d405c693d9a6f21b6f5cd846a2722cabd898a1e680dc976abc3e0c4b6edae623854e + checksum: bd549b54283034dd3e2f6c4b41b99a0caba0ddc8e9418490a611136ddb01e62235f14b233fcc172902fd1d18eec6e029245d22212566ea5cb5e24c7450d6005d languageName: node linkType: hard @@ -1533,14 +1406,14 @@ __metadata: linkType: hard "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:^7.27.1": - version: 7.28.6 - resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.28.6" + version: 7.29.0 + resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.29.0" dependencies: "@babel/helper-create-regexp-features-plugin": ^7.28.5 "@babel/helper-plugin-utils": ^7.28.6 peerDependencies: "@babel/core": ^7.0.0 - checksum: 3f2e2b85199adfdc3297983412c2ecdacc0004bc5ac3263d29909219b8c5afa2ca49e3b6efc11ce67034d5780eef27882a94873444cf27d841d7fa7f01d7dcff + checksum: 7fa7b773259a578c9e01c80946f75ecc074520064aa7a87a65db06c7df70766e2fa6be78cda55fa9418a14e30b2b9d595484a46db48074d495d9f877a4276065 languageName: node linkType: hard @@ -1683,16 +1556,16 @@ __metadata: linkType: hard "@babel/plugin-transform-modules-systemjs@npm:^7.27.1": - version: 7.28.5 - resolution: "@babel/plugin-transform-modules-systemjs@npm:7.28.5" + version: 7.29.0 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.29.0" dependencies: - "@babel/helper-module-transforms": ^7.28.3 - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-module-transforms": ^7.28.6 + "@babel/helper-plugin-utils": ^7.28.6 "@babel/helper-validator-identifier": ^7.28.5 - "@babel/traverse": ^7.28.5 + "@babel/traverse": ^7.29.0 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 646748dcf968c107fedfbff38aa37f7a9ebf2ccdf51fd9f578c6cd323371db36bbc5fe0d995544db168f39be9bca32a85fbf3bfff4742d2bed22e21c2847fa46 + checksum: 36fd7bcd694549effdbdf733c32f0c9dbadea052316ff5e0830b07482a60c8ff1ee79850efff05e8046c4b99c241832f2c5267e0ae7c721c531c8ef12930c4b9 languageName: node linkType: hard @@ -1709,14 +1582,14 @@ __metadata: linkType: hard "@babel/plugin-transform-named-capturing-groups-regex@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.27.1" + version: 7.29.0 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.29.0" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.27.1 - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-create-regexp-features-plugin": ^7.28.5 + "@babel/helper-plugin-utils": ^7.28.6 peerDependencies: "@babel/core": ^7.0.0 - checksum: a711c92d9753df26cefc1792481e5cbff4fe4f32b383d76b25e36fa865d8023b1b9aa6338cf18f5c0e864c71a7fbe8115e840872ccd61a914d9953849c68de7d + checksum: ed8c27699ca82a6c01cbfd39f3de16b90cfea4f8146a358057f76df290d308a66a8bd2e6734e6a87f68c18576e15d2d70548a84cd474d26fdf256c3f5ae44d8c languageName: node linkType: hard @@ -1851,13 +1724,13 @@ __metadata: linkType: hard "@babel/plugin-transform-regenerator@npm:^7.28.3": - version: 7.28.6 - resolution: "@babel/plugin-transform-regenerator@npm:7.28.6" + version: 7.29.0 + resolution: "@babel/plugin-transform-regenerator@npm:7.29.0" dependencies: "@babel/helper-plugin-utils": ^7.28.6 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 1c1e3149a14e2cb695483f69f4ec18d1b820b23fe3b766a1e2efdbc2af0ed8acea6ea9438e8bc1496aab51e598a824428cec28431f1c1ea21d9599b46bf4aa24 + checksum: f48bc814f11239f2bfe010a6e29d5ac2443e7b1d8004e7c022effa111b743491127acf8644cfef475edb86b91f123829585867bc13762652aabd9b85ed6ce61e languageName: node linkType: hard @@ -2103,45 +1976,14 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.12.5": +"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.21.0": version: 7.28.6 resolution: "@babel/runtime@npm:7.28.6" checksum: 42d8a868c2fc2e9a77927945a6daa7ec03c7ea49e611e0d15442933cdabb12f20e3a6849c729259076c10a4247adec229331d1f94c2d0073ea0979d7853e29fd languageName: node linkType: hard -"@babel/runtime@npm:^7.21.0": - version: 7.26.10 - resolution: "@babel/runtime@npm:7.26.10" - dependencies: - regenerator-runtime: ^0.14.0 - checksum: 22d2e0abb86e90de489ab16bb578db6fe2b63a88696db431198b24963749820c723f1982298cdbbea187f7b2b80fb4d98a514faf114ddb2fdc14a4b96277b955 - languageName: node - linkType: hard - -"@babel/template@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/template@npm:7.25.9" - dependencies: - "@babel/code-frame": ^7.25.9 - "@babel/parser": ^7.25.9 - "@babel/types": ^7.25.9 - checksum: 103641fea19c7f4e82dc913aa6b6ac157112a96d7c724d513288f538b84bae04fb87b1f1e495ac1736367b1bc30e10f058b30208fb25f66038e1f1eb4e426472 - languageName: node - linkType: hard - -"@babel/template@npm:^7.27.1, @babel/template@npm:^7.27.2": - version: 7.27.2 - resolution: "@babel/template@npm:7.27.2" - dependencies: - "@babel/code-frame": ^7.27.1 - "@babel/parser": ^7.27.2 - "@babel/types": ^7.27.1 - checksum: ff5628bc066060624afd970616090e5bba91c6240c2e4b458d13267a523572cbfcbf549391eec8217b94b064cf96571c6273f0c04b28a8567b96edc675c28e27 - languageName: node - linkType: hard - -"@babel/template@npm:^7.28.6": +"@babel/template@npm:^7.27.2, @babel/template@npm:^7.28.6": version: 7.28.6 resolution: "@babel/template@npm:7.28.6" dependencies: @@ -2152,85 +1994,35 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.25.9": - version: 7.26.4 - resolution: "@babel/traverse@npm:7.26.4" - dependencies: - "@babel/code-frame": ^7.26.2 - "@babel/generator": ^7.26.3 - "@babel/parser": ^7.26.3 - "@babel/template": ^7.25.9 - "@babel/types": ^7.26.3 - debug: ^4.3.1 - globals: ^11.1.0 - checksum: dcdf51b27ab640291f968e4477933465c2910bfdcbcff8f5315d1f29b8ff861864f363e84a71fb489f5e9708e8b36b7540608ce019aa5e57ef7a4ba537e62700 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.27.3, @babel/traverse@npm:^7.28.0": - version: 7.28.0 - resolution: "@babel/traverse@npm:7.28.0" - dependencies: - "@babel/code-frame": ^7.27.1 - "@babel/generator": ^7.28.0 - "@babel/helper-globals": ^7.28.0 - "@babel/parser": ^7.28.0 - "@babel/template": ^7.27.2 - "@babel/types": ^7.28.0 - debug: ^4.3.1 - checksum: f1b6ed2a37f593ee02db82521f8d54c8540a7ec2735c6c127ba687de306d62ac5a7c6471819783128e0b825c4f7e374206ebbd1daf00d07f05a4528f5b1b4c07 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.28.3, @babel/traverse@npm:^7.28.5, @babel/traverse@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/traverse@npm:7.28.6" +"@babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.28.0, @babel/traverse@npm:^7.28.3, @babel/traverse@npm:^7.28.5, @babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/traverse@npm:7.29.0" dependencies: - "@babel/code-frame": ^7.28.6 - "@babel/generator": ^7.28.6 + "@babel/code-frame": ^7.29.0 + "@babel/generator": ^7.29.0 "@babel/helper-globals": ^7.28.0 - "@babel/parser": ^7.28.6 + "@babel/parser": ^7.29.0 "@babel/template": ^7.28.6 - "@babel/types": ^7.28.6 + "@babel/types": ^7.29.0 debug: ^4.3.1 - checksum: 07bc23b720d111a20382fcdba776b800a7c1f94e35f8e4f417869f6769ba67c2b9573c8240924ca3b0ee5a88fa7ed048efb289e8b324f5cb4971e771174a0d32 - languageName: node - linkType: hard - -"@babel/types@npm:^7.24.7, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0, @babel/types@npm:^7.26.3, @babel/types@npm:^7.4.4": - version: 7.26.3 - resolution: "@babel/types@npm:7.26.3" - dependencies: - "@babel/helper-string-parser": ^7.25.9 - "@babel/helper-validator-identifier": ^7.25.9 - checksum: 195f428080dcaadbcecc9445df7f91063beeaa91b49ccd78f38a5af6b75a6a58391d0c6614edb1ea322e57889a1684a0aab8e667951f820196901dd341f931e9 - languageName: node - linkType: hard - -"@babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.0, @babel/types@npm:^7.28.2": - version: 7.28.2 - resolution: "@babel/types@npm:7.28.2" - dependencies: - "@babel/helper-string-parser": ^7.27.1 - "@babel/helper-validator-identifier": ^7.27.1 - checksum: 2218f0996d5fbadc4e3428c4c38f4ed403f0e2634e3089beba2c89783268c0c1d796a23e65f9f1ff8547b9061ae1a67691c76dc27d0b457e5fa9f2dd4e022e49 + checksum: fbb5085aa525b5d4ecd9fe2f5885d88413fff6ad9c0fac244c37f96069b6d3af9ce825750cd16af1d97d26fa3d354b38dbbdb5f31430e0d99ed89660ab65430e languageName: node linkType: hard -"@babel/types@npm:^7.28.5, @babel/types@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/types@npm:7.28.6" +"@babel/types@npm:^7.24.7, @babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.5, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.4.4": + version: 7.29.0 + resolution: "@babel/types@npm:7.29.0" dependencies: "@babel/helper-string-parser": ^7.27.1 "@babel/helper-validator-identifier": ^7.28.5 - checksum: f76556cda59be337cc10dc68b2a9a947c10de018998bab41076e7b7e4489b28dd53299f98f22eec0774264c989515e6fdc56de91c73e3aa396367bb953200a6a + checksum: 83f190438e94c22b2574aaeef7501830311ef266eaabfb06523409f64e2fe855e522951607085d71cad286719adef14e1ba37b671f334a7cd25b0f8506a01e0b languageName: node linkType: hard "@braintree/sanitize-url@npm:^7.1.1": - version: 7.1.1 - resolution: "@braintree/sanitize-url@npm:7.1.1" - checksum: bdfb6add95e97c5a611597197cd8385c6592d340a688bfbb176a1799bde64b9ffa1e723a7bac908d61fdecfccf4301332cdebaa4a1650c2616b5269084d9c8e4 + version: 7.1.2 + resolution: "@braintree/sanitize-url@npm:7.1.2" + checksum: ca787264bbea2a3c02ce5cd5e08a1debf1ffff1c87b954ed2522d816fc3f3a9b93a5a55056dfe394d86c780ced35ee2fc06abbffd0f5f2e95264f7b62cb29d66 languageName: node linkType: hard @@ -2255,9 +2047,9 @@ __metadata: linkType: hard "@chainsafe/is-ip@npm:^2.0.1": - version: 2.0.2 - resolution: "@chainsafe/is-ip@npm:2.0.2" - checksum: 2600350ba1c8fbad5d1ebee71317beeb29fbaebf43780d89e30f8c6c2d27b95ebdab0284dfbab7336b5eb6d8ffcc7081e3e4c5b221889dc366463f83bbe38adb + version: 2.1.0 + resolution: "@chainsafe/is-ip@npm:2.1.0" + checksum: 9cf32560213f4e3f57ae9653a6a3b26b27f64a7bea20a23a0a161265d15003c097c924cd0b230375eb92706ced422e7c947313fd13e431f5494dc55dbf5ebbe5 languageName: node linkType: hard @@ -2352,9 +2144,9 @@ __metadata: linkType: hard "@csstools/css-syntax-patches-for-csstree@npm:^1.0.21": - version: 1.0.25 - resolution: "@csstools/css-syntax-patches-for-csstree@npm:1.0.25" - checksum: 8bc68ad4fc7b9cf3d31c2b65424ead8114c3778d9b3d7c6091e7cbde186e1ce91cff8d913c86509b9cfba48b287f3418bce9083386d5153906ed97617f0c8ec6 + version: 1.0.26 + resolution: "@csstools/css-syntax-patches-for-csstree@npm:1.0.26" + checksum: 45331c2fc6f8833e6672a7ec5fafd475c6e57b88e9245c555b7567118ff45e81e45bade5e33114315a9b18b79f66d4b48663bebde0056d449e026817ba9ebf6a languageName: node linkType: hard @@ -2400,9 +2192,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/aix-ppc64@npm:0.25.8" +"@esbuild/aix-ppc64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/aix-ppc64@npm:0.25.12" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard @@ -2421,9 +2213,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/android-arm64@npm:0.25.8" +"@esbuild/android-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/android-arm64@npm:0.25.12" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -2442,9 +2234,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/android-arm@npm:0.25.8" +"@esbuild/android-arm@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/android-arm@npm:0.25.12" conditions: os=android & cpu=arm languageName: node linkType: hard @@ -2463,9 +2255,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-x64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/android-x64@npm:0.25.8" +"@esbuild/android-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/android-x64@npm:0.25.12" conditions: os=android & cpu=x64 languageName: node linkType: hard @@ -2484,9 +2276,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/darwin-arm64@npm:0.25.8" +"@esbuild/darwin-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/darwin-arm64@npm:0.25.12" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -2505,9 +2297,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/darwin-x64@npm:0.25.8" +"@esbuild/darwin-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/darwin-x64@npm:0.25.12" conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -2526,9 +2318,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/freebsd-arm64@npm:0.25.8" +"@esbuild/freebsd-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/freebsd-arm64@npm:0.25.12" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard @@ -2547,9 +2339,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/freebsd-x64@npm:0.25.8" +"@esbuild/freebsd-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/freebsd-x64@npm:0.25.12" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard @@ -2568,9 +2360,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/linux-arm64@npm:0.25.8" +"@esbuild/linux-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-arm64@npm:0.25.12" conditions: os=linux & cpu=arm64 languageName: node linkType: hard @@ -2589,9 +2381,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/linux-arm@npm:0.25.8" +"@esbuild/linux-arm@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-arm@npm:0.25.12" conditions: os=linux & cpu=arm languageName: node linkType: hard @@ -2610,9 +2402,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/linux-ia32@npm:0.25.8" +"@esbuild/linux-ia32@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-ia32@npm:0.25.12" conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -2631,9 +2423,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/linux-loong64@npm:0.25.8" +"@esbuild/linux-loong64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-loong64@npm:0.25.12" conditions: os=linux & cpu=loong64 languageName: node linkType: hard @@ -2652,9 +2444,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/linux-mips64el@npm:0.25.8" +"@esbuild/linux-mips64el@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-mips64el@npm:0.25.12" conditions: os=linux & cpu=mips64el languageName: node linkType: hard @@ -2673,9 +2465,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/linux-ppc64@npm:0.25.8" +"@esbuild/linux-ppc64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-ppc64@npm:0.25.12" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard @@ -2694,9 +2486,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/linux-riscv64@npm:0.25.8" +"@esbuild/linux-riscv64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-riscv64@npm:0.25.12" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard @@ -2715,9 +2507,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/linux-s390x@npm:0.25.8" +"@esbuild/linux-s390x@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-s390x@npm:0.25.12" conditions: os=linux & cpu=s390x languageName: node linkType: hard @@ -2736,9 +2528,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/linux-x64@npm:0.25.8" +"@esbuild/linux-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-x64@npm:0.25.12" conditions: os=linux & cpu=x64 languageName: node linkType: hard @@ -2757,9 +2549,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-arm64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/netbsd-arm64@npm:0.25.8" +"@esbuild/netbsd-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/netbsd-arm64@npm:0.25.12" conditions: os=netbsd & cpu=arm64 languageName: node linkType: hard @@ -2778,9 +2570,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/netbsd-x64@npm:0.25.8" +"@esbuild/netbsd-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/netbsd-x64@npm:0.25.12" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard @@ -2799,9 +2591,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-arm64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/openbsd-arm64@npm:0.25.8" +"@esbuild/openbsd-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/openbsd-arm64@npm:0.25.12" conditions: os=openbsd & cpu=arm64 languageName: node linkType: hard @@ -2820,9 +2612,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/openbsd-x64@npm:0.25.8" +"@esbuild/openbsd-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/openbsd-x64@npm:0.25.12" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard @@ -2841,9 +2633,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/openharmony-arm64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/openharmony-arm64@npm:0.25.8" +"@esbuild/openharmony-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/openharmony-arm64@npm:0.25.12" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard @@ -2862,9 +2654,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/sunos-x64@npm:0.25.8" +"@esbuild/sunos-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/sunos-x64@npm:0.25.12" conditions: os=sunos & cpu=x64 languageName: node linkType: hard @@ -2883,9 +2675,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/win32-arm64@npm:0.25.8" +"@esbuild/win32-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/win32-arm64@npm:0.25.12" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -2904,9 +2696,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/win32-ia32@npm:0.25.8" +"@esbuild/win32-ia32@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/win32-ia32@npm:0.25.12" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -2925,9 +2717,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.25.8": - version: 0.25.8 - resolution: "@esbuild/win32-x64@npm:0.25.8" +"@esbuild/win32-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/win32-x64@npm:0.25.12" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -2947,23 +2739,23 @@ __metadata: linkType: hard "@exodus/bytes@npm:^1.6.0": - version: 1.8.0 - resolution: "@exodus/bytes@npm:1.8.0" + version: 1.11.0 + resolution: "@exodus/bytes@npm:1.11.0" peerDependencies: - "@exodus/crypto": ^1.0.0-rc.4 + "@noble/hashes": ^1.8.0 || ^2.0.0 peerDependenciesMeta: - "@exodus/crypto": + "@noble/hashes": optional: true - checksum: 27ddf16dbaa99ae9b62fda23c47494ee182c77130760f78e7dff7594668ea00c2f803063d78f3c0f8670396e465428243484880589af3f025cd93f537682367c + checksum: 947bd4452450665b04b8f929e70edde0aeb6826cb9ee07b30301afa702c2c1a90bd8ac82e6463159fbc98587e91b1a690bc6dbf05d1d9d1dc5dc3508a3ecac40 languageName: node linkType: hard "@hono/node-server@npm:^1.19.7": - version: 1.19.8 - resolution: "@hono/node-server@npm:1.19.8" + version: 1.19.9 + resolution: "@hono/node-server@npm:1.19.9" peerDependencies: hono: ^4 - checksum: cac312f99a25408aac8fcb0852817a807afc326ea670e7a6cbfcf12c6ea891bd131b07465512c8212771faf41bf53d517925cde4aff95a258fb36a017c9f903d + checksum: 8ec9095c8b2679b2e958836806c659de45b0e74a0031dea93413d51a5eb89a79219bc9d55efc4f5fb2506ab83e15856bb009fb77b76c6689189b26d5eada25a4 languageName: node linkType: hard @@ -2975,18 +2767,13 @@ __metadata: linkType: hard "@iconify/utils@npm:^3.0.1": - version: 3.0.2 - resolution: "@iconify/utils@npm:3.0.2" + version: 3.1.0 + resolution: "@iconify/utils@npm:3.1.0" dependencies: "@antfu/install-pkg": ^1.1.0 - "@antfu/utils": ^9.2.0 "@iconify/types": ^2.0.0 - debug: ^4.4.1 - globals: ^15.15.0 - kolorist: ^1.8.0 - local-pkg: ^1.1.1 - mlly: ^1.7.4 - checksum: a71af73cdc198a4aafedb784d2283af2792c1c929f79ae115700b4b4fab74a545b817eff7ae701c90dcc2e4b14ea3c2300d84173149e74a544b0bb5a238cd7b8 + mlly: ^1.8.0 + checksum: b4055a322a13289740b2ecef424a1807ccb1567a200b716e4d1e2f40ad24dd9e24fa7b9a1aa1a275eea30ef3f08a32a4640a1a66f013d32cfe31117ac76b4075 languageName: node linkType: hard @@ -3240,7 +3027,7 @@ __metadata: languageName: node linkType: hard -"@inquirer/type@npm:^3.0.10, @inquirer/type@npm:^3.0.7": +"@inquirer/type@npm:^3.0.10, @inquirer/type@npm:^3.0.7, @inquirer/type@npm:^3.0.8": version: 3.0.10 resolution: "@inquirer/type@npm:3.0.10" peerDependencies: @@ -3252,18 +3039,6 @@ __metadata: languageName: node linkType: hard -"@inquirer/type@npm:^3.0.8": - version: 3.0.8 - resolution: "@inquirer/type@npm:3.0.8" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 361fa75c98f274462aaa3f2baf40ee43f284daaa64e3689a92863ed4ff63236ca3d40c6e715b3ff80c45feb6ab679792a6162e2d4521daff3929c490b0dddfcf - languageName: node - linkType: hard - "@isaacs/balanced-match@npm:^4.0.1": version: 4.0.1 resolution: "@isaacs/balanced-match@npm:4.0.1" @@ -3280,20 +3055,6 @@ __metadata: languageName: node linkType: hard -"@isaacs/cliui@npm:^8.0.2": - version: 8.0.2 - resolution: "@isaacs/cliui@npm:8.0.2" - dependencies: - string-width: ^5.1.2 - string-width-cjs: "npm:string-width@^4.2.0" - strip-ansi: ^7.0.1 - strip-ansi-cjs: "npm:strip-ansi@^6.0.1" - wrap-ansi: ^8.1.0 - wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" - checksum: 4a473b9b32a7d4d3cfb7a614226e555091ff0c5a29a1734c28c72a182c2f6699b26fc6b5c2131dfd841e86b185aea714c72201d7c98c2fba5f17709333a67aeb - languageName: node - linkType: hard - "@isaacs/fs-minipass@npm:^4.0.0": version: 4.0.1 resolution: "@isaacs/fs-minipass@npm:4.0.1" @@ -3310,24 +3071,23 @@ __metadata: languageName: node linkType: hard -"@jridgewell/gen-mapping@npm:^0.3.12": - version: 0.3.12 - resolution: "@jridgewell/gen-mapping@npm:0.3.12" +"@jridgewell/gen-mapping@npm:^0.3.12, @jridgewell/gen-mapping@npm:^0.3.5": + version: 0.3.13 + resolution: "@jridgewell/gen-mapping@npm:0.3.13" dependencies: "@jridgewell/sourcemap-codec": ^1.5.0 "@jridgewell/trace-mapping": ^0.3.24 - checksum: 56ee1631945084897f274e65348afbaca7970ce92e3c23b3a23b2fe5d0d2f0c67614f0df0f2bb070e585e944bbaaf0c11cee3a36318ab8a36af46f2fd566bc40 + checksum: f2105acefc433337145caa3c84bba286de954f61c0bc46279bbd85a9e6a02871089717fa060413cfb6a9d44189fe8313b2d1cabf3a2eb3284d208fd5f75c54ff languageName: node linkType: hard -"@jridgewell/gen-mapping@npm:^0.3.2, @jridgewell/gen-mapping@npm:^0.3.5": - version: 0.3.8 - resolution: "@jridgewell/gen-mapping@npm:0.3.8" +"@jridgewell/remapping@npm:^2.3.5": + version: 2.3.5 + resolution: "@jridgewell/remapping@npm:2.3.5" dependencies: - "@jridgewell/set-array": ^1.2.1 - "@jridgewell/sourcemap-codec": ^1.4.10 + "@jridgewell/gen-mapping": ^0.3.5 "@jridgewell/trace-mapping": ^0.3.24 - checksum: c0687b5227461717aa537fe71a42e356bcd1c43293b3353796a148bf3b0d6f59109def46c22f05b60e29a46f19b2e4676d027959a7c53a6c92b9d5b0d87d0420 + checksum: 4a66a7397c3dc9c6b5c14a0024b1f98c5e1d90a0dbc1e5955b5038f2db339904df2a0ee8a66559fafb4fc23ff33700a2639fd40bbdd2e9e82b58b3bdf83738e3 languageName: node linkType: hard @@ -3338,31 +3098,17 @@ __metadata: languageName: node linkType: hard -"@jridgewell/set-array@npm:^1.2.1": - version: 1.2.1 - resolution: "@jridgewell/set-array@npm:1.2.1" - checksum: 832e513a85a588f8ed4f27d1279420d8547743cc37fcad5a5a76fc74bb895b013dfe614d0eed9cb860048e6546b798f8f2652020b4b2ba0561b05caa8c654b10 - languageName: node - linkType: hard - "@jridgewell/source-map@npm:^0.3.3": - version: 0.3.6 - resolution: "@jridgewell/source-map@npm:0.3.6" + version: 0.3.11 + resolution: "@jridgewell/source-map@npm:0.3.11" dependencies: "@jridgewell/gen-mapping": ^0.3.5 "@jridgewell/trace-mapping": ^0.3.25 - checksum: c9dc7d899397df95e3c9ec287b93c0b56f8e4453cd20743e2b9c8e779b1949bc3cccf6c01bb302779e46560eb45f62ea38d19fedd25370d814734268450a9f30 - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0": - version: 1.5.0 - resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" - checksum: 05df4f2538b3b0f998ea4c1cd34574d0feba216fa5d4ccaef0187d12abf82eafe6021cec8b49f9bb4d90f2ba4582ccc581e72986a5fcf4176ae0cfeb04cf52ec + checksum: c8a0011cc67e701f270fa042e32b312f382c413bcc70ca9c03684687cbf5b64d5eed87d4afa36dddaabe60ab3da6db4935f878febd9cfc7f82724ea1a114d344 languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.5.5": +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0, @jridgewell/sourcemap-codec@npm:^1.5.5": version: 1.5.5 resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" checksum: c2e36e67971f719a8a3a85ef5a5f580622437cc723c35d03ebd0c9c0b06418700ef006f58af742791f71f6a4fc68fcfaf1f6a74ec2f9a3332860e9373459dae7 @@ -3379,27 +3125,26 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": - version: 0.3.25 - resolution: "@jridgewell/trace-mapping@npm:0.3.25" +"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.28": + version: 0.3.31 + resolution: "@jridgewell/trace-mapping@npm:0.3.31" dependencies: "@jridgewell/resolve-uri": ^3.1.0 "@jridgewell/sourcemap-codec": ^1.4.14 - checksum: 9d3c40d225e139987b50c48988f8717a54a8c994d8a948ee42e1412e08988761d0754d7d10b803061cc3aebf35f92a5dbbab493bd0e1a9ef9e89a2130e83ba34 + checksum: af8fda2431348ad507fbddf8e25f5d08c79ecc94594061ce402cf41bc5aba1a7b3e59bf0fd70a619b35f33983a3f488ceeba8faf56bff784f98bb5394a8b7d47 languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.28": - version: 0.3.29 - resolution: "@jridgewell/trace-mapping@npm:0.3.29" - dependencies: - "@jridgewell/resolve-uri": ^3.1.0 - "@jridgewell/sourcemap-codec": ^1.4.14 - checksum: 5e92eeafa5131a4f6b7122063833d657f885cb581c812da54f705d7a599ff36a75a4a093a83b0f6c7e95642f5772dd94753f696915e8afea082237abf7423ca3 +"@jsonjoy.com/base64@npm:17.65.0": + version: 17.65.0 + resolution: "@jsonjoy.com/base64@npm:17.65.0" + peerDependencies: + tslib: 2 + checksum: ed222c7e4575d1098a1e4e4c5254ebc0cc7c603d5b2aa2f33edbd1aaf2b122b6ae371f52836fb4591d07312634d75c5afb5ce32665661e23135dfd1593526c70 languageName: node linkType: hard -"@jsonjoy.com/base64@npm:^1.1.1": +"@jsonjoy.com/base64@npm:^1.1.2": version: 1.1.2 resolution: "@jsonjoy.com/base64@npm:1.1.2" peerDependencies: @@ -3408,26 +3153,225 @@ __metadata: languageName: node linkType: hard -"@jsonjoy.com/json-pack@npm:^1.0.3": - version: 1.1.1 - resolution: "@jsonjoy.com/json-pack@npm:1.1.1" +"@jsonjoy.com/buffers@npm:17.65.0, @jsonjoy.com/buffers@npm:^17.65.0": + version: 17.65.0 + resolution: "@jsonjoy.com/buffers@npm:17.65.0" + peerDependencies: + tslib: 2 + checksum: cd73e975d7c23eb25be779bae5e2d2a9ee8290d5df767cea6b6133dc4ef4f15cdf6f01c2fe56012cf7cd935ec717a149a5c8e6546358e54efa08ed5dd9ee2f01 + languageName: node + linkType: hard + +"@jsonjoy.com/buffers@npm:^1.0.0, @jsonjoy.com/buffers@npm:^1.2.0": + version: 1.2.1 + resolution: "@jsonjoy.com/buffers@npm:1.2.1" + peerDependencies: + tslib: 2 + checksum: 5de11264a7ffe62e5ee3e4f9328bb01cb18dd9d4b977ce1a98e134860c630ae801cf535b78f7a618c33955061d49f0b09699eb77b10e0e45b942f7bb48a19791 + languageName: node + linkType: hard + +"@jsonjoy.com/codegen@npm:17.65.0": + version: 17.65.0 + resolution: "@jsonjoy.com/codegen@npm:17.65.0" + peerDependencies: + tslib: 2 + checksum: d3e7aff13ebd33a6a6eb714a80e9ad4cdc22805922db73723b36a9741f79f5ace3e8379560e4e6eab28fe3881b6c2ef9198ab8ef47b07eae0bf084da3ad2cfcb + languageName: node + linkType: hard + +"@jsonjoy.com/codegen@npm:^1.0.0": + version: 1.0.0 + resolution: "@jsonjoy.com/codegen@npm:1.0.0" + peerDependencies: + tslib: 2 + checksum: 77383ed703dacc0ee35783589f3289e464d9fd047675f2f628b4d8a567c2b9c87f0121f4445203d51645b5777d24c3b50ed7e12525f4064a0614caae81b1dc2e + languageName: node + linkType: hard + +"@jsonjoy.com/fs-core@npm:4.56.10": + version: 4.56.10 + resolution: "@jsonjoy.com/fs-core@npm:4.56.10" + dependencies: + "@jsonjoy.com/fs-node-builtins": 4.56.10 + "@jsonjoy.com/fs-node-utils": 4.56.10 + thingies: ^2.5.0 + peerDependencies: + tslib: 2 + checksum: d6bf86ec80ad33753b832735e5817b262d9b4667c687eed659bcebdaf19d0c2239b9d6f08b8fb366c5b28083a00fffb9840a7d552e2567d818c0fa886d20e24b + languageName: node + linkType: hard + +"@jsonjoy.com/fs-fsa@npm:4.56.10": + version: 4.56.10 + resolution: "@jsonjoy.com/fs-fsa@npm:4.56.10" + dependencies: + "@jsonjoy.com/fs-core": 4.56.10 + "@jsonjoy.com/fs-node-builtins": 4.56.10 + "@jsonjoy.com/fs-node-utils": 4.56.10 + thingies: ^2.5.0 + peerDependencies: + tslib: 2 + checksum: f3eecd70f8151074b16b4c3e04efac685d4fe19b19c49bbe798f99f501cc9cd31c3a18a7cc3fd9060b42ea7ed5d37452eab6554c992ed560747a4e8b12984ffe + languageName: node + linkType: hard + +"@jsonjoy.com/fs-node-builtins@npm:4.56.10": + version: 4.56.10 + resolution: "@jsonjoy.com/fs-node-builtins@npm:4.56.10" + peerDependencies: + tslib: 2 + checksum: b383f3f0c0c66a5ba22dd922ca21c3a08d37060c469f62e50f74b3f99f874a11e4b0099ba92da53c818cdb31b39068393466374858cdcbaea0fd17904d2c3dd6 + languageName: node + linkType: hard + +"@jsonjoy.com/fs-node-to-fsa@npm:4.56.10": + version: 4.56.10 + resolution: "@jsonjoy.com/fs-node-to-fsa@npm:4.56.10" + dependencies: + "@jsonjoy.com/fs-fsa": 4.56.10 + "@jsonjoy.com/fs-node-builtins": 4.56.10 + "@jsonjoy.com/fs-node-utils": 4.56.10 + peerDependencies: + tslib: 2 + checksum: 1d798ddc5a2b36e1a173b73543a435bcf282ec195f0b78cc500b73ecd521dbaba250855a6883d2406d264b95582e8fca4b1e4094d190fc64252408c399c666e7 + languageName: node + linkType: hard + +"@jsonjoy.com/fs-node-utils@npm:4.56.10": + version: 4.56.10 + resolution: "@jsonjoy.com/fs-node-utils@npm:4.56.10" + dependencies: + "@jsonjoy.com/fs-node-builtins": 4.56.10 + peerDependencies: + tslib: 2 + checksum: 9beb585652e7699c9a8526737e5a20418586beb3b07b57930cd34ea2eef0acc2179c9987f024b30575aee9eaed079dabf236757a8abb60f7dd3f6cd25708c494 + languageName: node + linkType: hard + +"@jsonjoy.com/fs-node@npm:4.56.10": + version: 4.56.10 + resolution: "@jsonjoy.com/fs-node@npm:4.56.10" + dependencies: + "@jsonjoy.com/fs-core": 4.56.10 + "@jsonjoy.com/fs-node-builtins": 4.56.10 + "@jsonjoy.com/fs-node-utils": 4.56.10 + "@jsonjoy.com/fs-print": 4.56.10 + "@jsonjoy.com/fs-snapshot": 4.56.10 + glob-to-regex.js: ^1.0.0 + thingies: ^2.5.0 + peerDependencies: + tslib: 2 + checksum: 898ecdb4a3ca782de39c5a5985710f031da9d17eb9117ef07d7e47ef91a5fbacec4ecefb6978026201d5638eed9a13e65d7b888ba20d418346a7924227c8dc57 + languageName: node + linkType: hard + +"@jsonjoy.com/fs-print@npm:4.56.10": + version: 4.56.10 + resolution: "@jsonjoy.com/fs-print@npm:4.56.10" + dependencies: + "@jsonjoy.com/fs-node-utils": 4.56.10 + tree-dump: ^1.1.0 + peerDependencies: + tslib: 2 + checksum: 9eff4f179624f9bee799e2a7abcc311a512284fae2c149cd85378604e407bba613d95af065275caf37e0a16a015a040cb4a99cec8c51ac6d393bcf9c343c0d8e + languageName: node + linkType: hard + +"@jsonjoy.com/fs-snapshot@npm:4.56.10": + version: 4.56.10 + resolution: "@jsonjoy.com/fs-snapshot@npm:4.56.10" + dependencies: + "@jsonjoy.com/buffers": ^17.65.0 + "@jsonjoy.com/fs-node-utils": 4.56.10 + "@jsonjoy.com/json-pack": ^17.65.0 + "@jsonjoy.com/util": ^17.65.0 + peerDependencies: + tslib: 2 + checksum: 8abbc8171ab0b30eca5b1f06f1a5fcaf1d04ca342fd9fca497571cbfd4a05c444773945222f2b4cda952931d6703dff743ee554c78ca447d2051698f74c6595c + languageName: node + linkType: hard + +"@jsonjoy.com/json-pack@npm:^1.11.0": + version: 1.21.0 + resolution: "@jsonjoy.com/json-pack@npm:1.21.0" dependencies: - "@jsonjoy.com/base64": ^1.1.1 - "@jsonjoy.com/util": ^1.1.2 + "@jsonjoy.com/base64": ^1.1.2 + "@jsonjoy.com/buffers": ^1.2.0 + "@jsonjoy.com/codegen": ^1.0.0 + "@jsonjoy.com/json-pointer": ^1.0.2 + "@jsonjoy.com/util": ^1.9.0 hyperdyperid: ^1.2.0 - thingies: ^1.20.0 + thingies: ^2.5.0 + tree-dump: ^1.1.0 peerDependencies: tslib: 2 - checksum: bf1065b60c65bc0f3b3c1d496b8c65152ec23ecaefee8a5ff26dc7bc197aff541f15d1e1330bbd8b33b1c25d740406fc3c5f6d9da261ec6f1a753ac08fb0eb85 + checksum: 653b02514bd4ca5e57f72d1fe1b57181767001a4b2615f35135085309cc91fd47f7421c17a465becc76d986871831d4a1cb68506720547e7e7fc0822d6bc5092 languageName: node linkType: hard -"@jsonjoy.com/util@npm:^1.1.2, @jsonjoy.com/util@npm:^1.3.0": - version: 1.5.0 - resolution: "@jsonjoy.com/util@npm:1.5.0" +"@jsonjoy.com/json-pack@npm:^17.65.0": + version: 17.65.0 + resolution: "@jsonjoy.com/json-pack@npm:17.65.0" + dependencies: + "@jsonjoy.com/base64": 17.65.0 + "@jsonjoy.com/buffers": 17.65.0 + "@jsonjoy.com/codegen": 17.65.0 + "@jsonjoy.com/json-pointer": 17.65.0 + "@jsonjoy.com/util": 17.65.0 + hyperdyperid: ^1.2.0 + thingies: ^2.5.0 + tree-dump: ^1.1.0 + peerDependencies: + tslib: 2 + checksum: 8147d2f586f03e6b1f3f0f9a6dd1123d99246cef79c5a2814cb5fe01859577b8c5fe2b34c42e59e468ca11d29657c1f4a4bda5836a4b3218edf830eca82412da + languageName: node + linkType: hard + +"@jsonjoy.com/json-pointer@npm:17.65.0": + version: 17.65.0 + resolution: "@jsonjoy.com/json-pointer@npm:17.65.0" + dependencies: + "@jsonjoy.com/util": 17.65.0 + peerDependencies: + tslib: 2 + checksum: 608c5b0f1a4861c6883d31d8f90b4f5b89a86b6f68f44b902a71569292c4d78349b1824798cbf5715117453d1e2254ee1de66484aacf210651e15c5820a9d8ac + languageName: node + linkType: hard + +"@jsonjoy.com/json-pointer@npm:^1.0.2": + version: 1.0.2 + resolution: "@jsonjoy.com/json-pointer@npm:1.0.2" + dependencies: + "@jsonjoy.com/codegen": ^1.0.0 + "@jsonjoy.com/util": ^1.9.0 + peerDependencies: + tslib: 2 + checksum: 93b45eb2e5ea3864778dab45c9fd2313cd9fb0fc9fa9a6401c8dea0365e44551fa8debbf3d0efb8b5131c0fde689f4509248b3e2ba12852a8c75739028ec3c1b + languageName: node + linkType: hard + +"@jsonjoy.com/util@npm:17.65.0, @jsonjoy.com/util@npm:^17.65.0": + version: 17.65.0 + resolution: "@jsonjoy.com/util@npm:17.65.0" + dependencies: + "@jsonjoy.com/buffers": 17.65.0 + "@jsonjoy.com/codegen": 17.65.0 + peerDependencies: + tslib: 2 + checksum: 6fa908aa5e393dce40091908e94ee1963292219c50f4122cb3056cccb69a90380efe78a4595fd850f4da4a60ee3894b679f31ec285c831b88a8dc47e8d6324ba + languageName: node + linkType: hard + +"@jsonjoy.com/util@npm:^1.9.0": + version: 1.9.0 + resolution: "@jsonjoy.com/util@npm:1.9.0" + dependencies: + "@jsonjoy.com/buffers": ^1.0.0 + "@jsonjoy.com/codegen": ^1.0.0 peerDependencies: tslib: 2 - checksum: 62892928e1223798e3d910be8dde4fdceaddf2ebdd4bdc0c50495b8ee33503317adf7b5118cd8f5a63045e3f232d70e95fb0279828caf1ec392ffeeb7ea129b8 + checksum: a22c49af0736cede94c24ad8da7230f42697eb5c4a6016450d5bf1cbcb51cd5b45a08989e7ec4cad1cc47718cb5b26e0ba583189f238d095eae4b15cbbe8c9e7 languageName: node linkType: hard @@ -3438,6 +3382,13 @@ __metadata: languageName: node linkType: hard +"@kurkle/color@npm:^0.3.0": + version: 0.3.4 + resolution: "@kurkle/color@npm:0.3.4" + checksum: b95c6abe0241ba1745b3c84de3b464296b95ce577110b54f46e6c6dcc9a0966491533df43812bd6c66f92cf818e385d1390b280cd5851d4afb52fc37f8a6c0b9 + languageName: node + linkType: hard + "@leichtgewicht/ip-codec@npm:^2.0.1": version: 2.0.5 resolution: "@leichtgewicht/ip-codec@npm:2.0.5" @@ -3768,7 +3719,7 @@ __metadata: languageName: node linkType: hard -"@napi-rs/wasm-runtime@npm:^1.1.0": +"@napi-rs/wasm-runtime@npm:^1.1.1": version: 1.1.1 resolution: "@napi-rs/wasm-runtime@npm:1.1.1" dependencies: @@ -3791,14 +3742,14 @@ __metadata: languageName: node linkType: hard -"@ngtools/webpack@npm:20.3.14": - version: 20.3.14 - resolution: "@ngtools/webpack@npm:20.3.14" +"@ngtools/webpack@npm:20.3.15": + version: 20.3.15 + resolution: "@ngtools/webpack@npm:20.3.15" peerDependencies: "@angular/compiler-cli": ^20.0.0 typescript: ">=5.8 <6.0" webpack: ^5.54.0 - checksum: 8a8a35d894245c1e7e7801bbeecbc5c2b64addb5b6be4fd402595eb42aefbe8177213cb0a8f10198b06cec68ebf2fc976d94d1eedfd0db48cccc07d3d804e8fd + checksum: 203870570519f64013908014f0ec9556987046363b0ca0abc9ab242267123ce5ae9dacef17a363e89c482a631d130e401b849087d87748ff139344f3242d6099 languageName: node linkType: hard @@ -3829,364 +3780,363 @@ __metadata: languageName: node linkType: hard -"@npmcli/agent@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/agent@npm:3.0.0" +"@npmcli/agent@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/agent@npm:4.0.0" dependencies: agent-base: ^7.1.0 http-proxy-agent: ^7.0.0 https-proxy-agent: ^7.0.1 - lru-cache: ^10.0.1 + lru-cache: ^11.2.1 socks-proxy-agent: ^8.0.3 - checksum: e8fc25d536250ed3e669813b36e8c6d805628b472353c57afd8c4fde0fcfcf3dda4ffe22f7af8c9070812ec2e7a03fb41d7151547cef3508efe661a5a3add20f + checksum: 89ae20b44859ff8d4de56ade319d8ceaa267a0742d6f7345fe98aa5cd8614ced7db85ea4dc5bfbd6614dbb200a10b134e087143582534c939e8a02219e8665c8 languageName: node linkType: hard -"@npmcli/fs@npm:^4.0.0": - version: 4.0.0 - resolution: "@npmcli/fs@npm:4.0.0" +"@npmcli/fs@npm:^5.0.0": + version: 5.0.0 + resolution: "@npmcli/fs@npm:5.0.0" dependencies: semver: ^7.3.5 - checksum: 68951c589e9a4328698a35fd82fe71909a257d6f2ede0434d236fa55634f0fbcad9bb8755553ce5849bd25ee6f019f4d435921ac715c853582c4a7f5983c8d4a + checksum: 897dac32eb37e011800112d406b9ea2ebd96f1dab01bb8fbeb59191b86f6825dffed6a89f3b6c824753d10f8735b76d630927bd7610e9e123b129ef2e5f02cb5 languageName: node linkType: hard -"@npmcli/git@npm:^6.0.0": - version: 6.0.1 - resolution: "@npmcli/git@npm:6.0.1" +"@npmcli/git@npm:^7.0.0": + version: 7.0.1 + resolution: "@npmcli/git@npm:7.0.1" dependencies: - "@npmcli/promise-spawn": ^8.0.0 - ini: ^5.0.0 - lru-cache: ^10.0.1 - npm-pick-manifest: ^10.0.0 - proc-log: ^5.0.0 - promise-inflight: ^1.0.1 + "@npmcli/promise-spawn": ^9.0.0 + ini: ^6.0.0 + lru-cache: ^11.2.1 + npm-pick-manifest: ^11.0.1 + proc-log: ^6.0.0 promise-retry: ^2.0.1 semver: ^7.3.5 - which: ^5.0.0 - checksum: 2cdefa8c714861a73ff5afb262259ff968fa5c45224f7748e55ab1952eee78183094331570fa5f4cc92071f274dfdc0e072cf4902d2638c43b832a364363f33d + which: ^6.0.0 + checksum: 7874ebf952c35b33d9719924996bf033897c63b21fc4ec8b039a852d724048b5f417a5d1ac6a623a6d40e05c56b27f4a3dfe47d5774e9ce88a924903d34f76cd languageName: node linkType: hard -"@npmcli/installed-package-contents@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/installed-package-contents@npm:3.0.0" +"@npmcli/installed-package-contents@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/installed-package-contents@npm:4.0.0" dependencies: - npm-bundled: ^4.0.0 - npm-normalize-package-bin: ^4.0.0 + npm-bundled: ^5.0.0 + npm-normalize-package-bin: ^5.0.0 bin: installed-package-contents: bin/index.js - checksum: b259157c682512b1eb8a3df58d0cdb73189befda1e5eca8a2c8e4128698a098aa93038931d45f819463fa0f9a5873f782936cf5ab0941f1d125387144361f577 + checksum: c94aa13d9f80849221b2bd4eb06f9b7db65dac74ac6176f2dbcba6810c4083240dacddb293a38cfcd5d8c09932aef983b7e01ef434e53d63416a5e8471804fdd languageName: node linkType: hard -"@npmcli/node-gyp@npm:^4.0.0": - version: 4.0.0 - resolution: "@npmcli/node-gyp@npm:4.0.0" - checksum: ea4ac6aa273d762a540841315c59c61f3e4ef182c29b1295c30f287cd9d0e33650cd60d626cdce38caf5cff43a5848ea6c213bad5f884110fc90beb167ccbc46 +"@npmcli/node-gyp@npm:^5.0.0": + version: 5.0.0 + resolution: "@npmcli/node-gyp@npm:5.0.0" + checksum: 6b257d2b220c58ed655c9e267b07daca854a4a0d041f542b6ce16e8bee3bdb5d912beb23b1f8a80f47d68d43f0c0bac214a1f7d48e3d60b8da0ec806d872c48a languageName: node linkType: hard -"@npmcli/package-json@npm:^6.0.0": - version: 6.1.0 - resolution: "@npmcli/package-json@npm:6.1.0" +"@npmcli/package-json@npm:^7.0.0": + version: 7.0.4 + resolution: "@npmcli/package-json@npm:7.0.4" dependencies: - "@npmcli/git": ^6.0.0 - glob: ^10.2.2 - hosted-git-info: ^8.0.0 - json-parse-even-better-errors: ^4.0.0 - normalize-package-data: ^7.0.0 - proc-log: ^5.0.0 + "@npmcli/git": ^7.0.0 + glob: ^13.0.0 + hosted-git-info: ^9.0.0 + json-parse-even-better-errors: ^5.0.0 + proc-log: ^6.0.0 semver: ^7.5.3 - checksum: 645ce40b159de40f292f0a12a6957eed5127ad1d8aada3f519279cf8700b629e1f51f8215532f33a0094337be571044f8e1a9066b45196447f54440c1326baaf + validate-npm-package-license: ^3.0.4 + checksum: 92c5ce8d47adc7dcf76bb393243cef217ed5a8b7f8ee06ab8a6c739c100b5a636d670d1ff4369e4ea85213d2b3ddaaec8bb2956639beec309df6c072d617e487 languageName: node linkType: hard -"@npmcli/promise-spawn@npm:^8.0.0": - version: 8.0.2 - resolution: "@npmcli/promise-spawn@npm:8.0.2" +"@npmcli/promise-spawn@npm:^9.0.0": + version: 9.0.1 + resolution: "@npmcli/promise-spawn@npm:9.0.1" dependencies: - which: ^5.0.0 - checksum: d8963742d01c5d0a40d68d1f1919f0e0cddaead05359abb4a2913362641855bc869dc30982f701dbdf6f079c68b41b2b4515d78d9f068d23aa8f7bf521916567 + which: ^6.0.0 + checksum: 0b193c58408421b5eb07808efde4a6674a977f7d9ced63b28e90d9a6e238522f1776ed4a9f4b6b5455eb2c497eccf8ab82ea94f3cd41140fceca794763bb3e35 languageName: node linkType: hard -"@npmcli/redact@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/redact@npm:3.0.0" - checksum: 449b73da396b93e42603342207aeada3ca1eed0b0da7ec143f8d10feb5697efd27c2d670aef69b1ef73653cf6a9d8b0ee84e1ab960a0f11cbc8e8b1901ec825f +"@npmcli/redact@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/redact@npm:4.0.0" + checksum: 4e029c44a8593304bb1aa5a8f1559cb8f37b4dc3880c589ce546da0b8cfa741d16a054db38ee309e81c2120c148ba33edbb3252f97a78b3234ba9ab3fa3e176c languageName: node linkType: hard -"@npmcli/run-script@npm:^9.0.0": - version: 9.0.2 - resolution: "@npmcli/run-script@npm:9.0.2" +"@npmcli/run-script@npm:^10.0.0": + version: 10.0.3 + resolution: "@npmcli/run-script@npm:10.0.3" dependencies: - "@npmcli/node-gyp": ^4.0.0 - "@npmcli/package-json": ^6.0.0 - "@npmcli/promise-spawn": ^8.0.0 - node-gyp: ^11.0.0 - proc-log: ^5.0.0 - which: ^5.0.0 - checksum: 85d83c093bfce589632e82b6c26e50a365a61a88e4ad27ba287563cbc6dc5ec05652de4ac60871b42b2c454209fd996d47889217d5358fdcfd0b0fbc109f46a4 + "@npmcli/node-gyp": ^5.0.0 + "@npmcli/package-json": ^7.0.0 + "@npmcli/promise-spawn": ^9.0.0 + node-gyp: ^12.1.0 + proc-log: ^6.0.0 + which: ^6.0.0 + checksum: 309c1e3caadd66cbae0f255adf05afde3e49f073e6fd316e0709ba378862ca18737c6ced52444ff2f242683cc41ec8fe26af5571d217c378c0247e1e5f2d2ba8 languageName: node linkType: hard -"@oxc-resolver/binding-android-arm-eabi@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-android-arm-eabi@npm:11.16.2" +"@oxc-resolver/binding-android-arm-eabi@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-android-arm-eabi@npm:11.17.0" conditions: os=android & cpu=arm languageName: node linkType: hard -"@oxc-resolver/binding-android-arm64@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-android-arm64@npm:11.16.2" +"@oxc-resolver/binding-android-arm64@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-android-arm64@npm:11.17.0" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-darwin-arm64@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-darwin-arm64@npm:11.16.2" +"@oxc-resolver/binding-darwin-arm64@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-darwin-arm64@npm:11.17.0" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-darwin-x64@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-darwin-x64@npm:11.16.2" +"@oxc-resolver/binding-darwin-x64@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-darwin-x64@npm:11.17.0" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@oxc-resolver/binding-freebsd-x64@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-freebsd-x64@npm:11.16.2" +"@oxc-resolver/binding-freebsd-x64@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-freebsd-x64@npm:11.17.0" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.16.2" +"@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.17.0" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm-musleabihf@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-arm-musleabihf@npm:11.16.2" +"@oxc-resolver/binding-linux-arm-musleabihf@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-linux-arm-musleabihf@npm:11.17.0" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm64-gnu@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-arm64-gnu@npm:11.16.2" +"@oxc-resolver/binding-linux-arm64-gnu@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-linux-arm64-gnu@npm:11.17.0" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm64-musl@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-arm64-musl@npm:11.16.2" +"@oxc-resolver/binding-linux-arm64-musl@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-linux-arm64-musl@npm:11.17.0" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@oxc-resolver/binding-linux-ppc64-gnu@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-ppc64-gnu@npm:11.16.2" +"@oxc-resolver/binding-linux-ppc64-gnu@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-linux-ppc64-gnu@npm:11.17.0" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-riscv64-gnu@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-riscv64-gnu@npm:11.16.2" +"@oxc-resolver/binding-linux-riscv64-gnu@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-linux-riscv64-gnu@npm:11.17.0" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-riscv64-musl@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-riscv64-musl@npm:11.16.2" +"@oxc-resolver/binding-linux-riscv64-musl@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-linux-riscv64-musl@npm:11.17.0" conditions: os=linux & cpu=riscv64 & libc=musl languageName: node linkType: hard -"@oxc-resolver/binding-linux-s390x-gnu@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-s390x-gnu@npm:11.16.2" +"@oxc-resolver/binding-linux-s390x-gnu@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-linux-s390x-gnu@npm:11.17.0" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-x64-gnu@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-x64-gnu@npm:11.16.2" +"@oxc-resolver/binding-linux-x64-gnu@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-linux-x64-gnu@npm:11.17.0" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-x64-musl@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-x64-musl@npm:11.16.2" +"@oxc-resolver/binding-linux-x64-musl@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-linux-x64-musl@npm:11.17.0" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@oxc-resolver/binding-openharmony-arm64@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-openharmony-arm64@npm:11.16.2" +"@oxc-resolver/binding-openharmony-arm64@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-openharmony-arm64@npm:11.17.0" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-wasm32-wasi@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-wasm32-wasi@npm:11.16.2" +"@oxc-resolver/binding-wasm32-wasi@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-wasm32-wasi@npm:11.17.0" dependencies: - "@napi-rs/wasm-runtime": ^1.1.0 + "@napi-rs/wasm-runtime": ^1.1.1 conditions: cpu=wasm32 languageName: node linkType: hard -"@oxc-resolver/binding-win32-arm64-msvc@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-win32-arm64-msvc@npm:11.16.2" +"@oxc-resolver/binding-win32-arm64-msvc@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-win32-arm64-msvc@npm:11.17.0" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-win32-ia32-msvc@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-win32-ia32-msvc@npm:11.16.2" +"@oxc-resolver/binding-win32-ia32-msvc@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-win32-ia32-msvc@npm:11.17.0" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@oxc-resolver/binding-win32-x64-msvc@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-win32-x64-msvc@npm:11.16.2" +"@oxc-resolver/binding-win32-x64-msvc@npm:11.17.0": + version: 11.17.0 + resolution: "@oxc-resolver/binding-win32-x64-msvc@npm:11.17.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@parcel/watcher-android-arm64@npm:2.5.0": - version: 2.5.0 - resolution: "@parcel/watcher-android-arm64@npm:2.5.0" +"@parcel/watcher-android-arm64@npm:2.5.6": + version: 2.5.6 + resolution: "@parcel/watcher-android-arm64@npm:2.5.6" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@parcel/watcher-darwin-arm64@npm:2.5.0": - version: 2.5.0 - resolution: "@parcel/watcher-darwin-arm64@npm:2.5.0" +"@parcel/watcher-darwin-arm64@npm:2.5.6": + version: 2.5.6 + resolution: "@parcel/watcher-darwin-arm64@npm:2.5.6" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@parcel/watcher-darwin-x64@npm:2.5.0": - version: 2.5.0 - resolution: "@parcel/watcher-darwin-x64@npm:2.5.0" +"@parcel/watcher-darwin-x64@npm:2.5.6": + version: 2.5.6 + resolution: "@parcel/watcher-darwin-x64@npm:2.5.6" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@parcel/watcher-freebsd-x64@npm:2.5.0": - version: 2.5.0 - resolution: "@parcel/watcher-freebsd-x64@npm:2.5.0" +"@parcel/watcher-freebsd-x64@npm:2.5.6": + version: 2.5.6 + resolution: "@parcel/watcher-freebsd-x64@npm:2.5.6" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@parcel/watcher-linux-arm-glibc@npm:2.5.0": - version: 2.5.0 - resolution: "@parcel/watcher-linux-arm-glibc@npm:2.5.0" +"@parcel/watcher-linux-arm-glibc@npm:2.5.6": + version: 2.5.6 + resolution: "@parcel/watcher-linux-arm-glibc@npm:2.5.6" conditions: os=linux & cpu=arm & libc=glibc languageName: node linkType: hard -"@parcel/watcher-linux-arm-musl@npm:2.5.0": - version: 2.5.0 - resolution: "@parcel/watcher-linux-arm-musl@npm:2.5.0" +"@parcel/watcher-linux-arm-musl@npm:2.5.6": + version: 2.5.6 + resolution: "@parcel/watcher-linux-arm-musl@npm:2.5.6" conditions: os=linux & cpu=arm & libc=musl languageName: node linkType: hard -"@parcel/watcher-linux-arm64-glibc@npm:2.5.0": - version: 2.5.0 - resolution: "@parcel/watcher-linux-arm64-glibc@npm:2.5.0" +"@parcel/watcher-linux-arm64-glibc@npm:2.5.6": + version: 2.5.6 + resolution: "@parcel/watcher-linux-arm64-glibc@npm:2.5.6" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@parcel/watcher-linux-arm64-musl@npm:2.5.0": - version: 2.5.0 - resolution: "@parcel/watcher-linux-arm64-musl@npm:2.5.0" +"@parcel/watcher-linux-arm64-musl@npm:2.5.6": + version: 2.5.6 + resolution: "@parcel/watcher-linux-arm64-musl@npm:2.5.6" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@parcel/watcher-linux-x64-glibc@npm:2.5.0": - version: 2.5.0 - resolution: "@parcel/watcher-linux-x64-glibc@npm:2.5.0" +"@parcel/watcher-linux-x64-glibc@npm:2.5.6": + version: 2.5.6 + resolution: "@parcel/watcher-linux-x64-glibc@npm:2.5.6" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@parcel/watcher-linux-x64-musl@npm:2.5.0": - version: 2.5.0 - resolution: "@parcel/watcher-linux-x64-musl@npm:2.5.0" +"@parcel/watcher-linux-x64-musl@npm:2.5.6": + version: 2.5.6 + resolution: "@parcel/watcher-linux-x64-musl@npm:2.5.6" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@parcel/watcher-win32-arm64@npm:2.5.0": - version: 2.5.0 - resolution: "@parcel/watcher-win32-arm64@npm:2.5.0" +"@parcel/watcher-win32-arm64@npm:2.5.6": + version: 2.5.6 + resolution: "@parcel/watcher-win32-arm64@npm:2.5.6" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@parcel/watcher-win32-ia32@npm:2.5.0": - version: 2.5.0 - resolution: "@parcel/watcher-win32-ia32@npm:2.5.0" +"@parcel/watcher-win32-ia32@npm:2.5.6": + version: 2.5.6 + resolution: "@parcel/watcher-win32-ia32@npm:2.5.6" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@parcel/watcher-win32-x64@npm:2.5.0": - version: 2.5.0 - resolution: "@parcel/watcher-win32-x64@npm:2.5.0" +"@parcel/watcher-win32-x64@npm:2.5.6": + version: 2.5.6 + resolution: "@parcel/watcher-win32-x64@npm:2.5.6" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@parcel/watcher@npm:^2.4.1": - version: 2.5.0 - resolution: "@parcel/watcher@npm:2.5.0" - dependencies: - "@parcel/watcher-android-arm64": 2.5.0 - "@parcel/watcher-darwin-arm64": 2.5.0 - "@parcel/watcher-darwin-x64": 2.5.0 - "@parcel/watcher-freebsd-x64": 2.5.0 - "@parcel/watcher-linux-arm-glibc": 2.5.0 - "@parcel/watcher-linux-arm-musl": 2.5.0 - "@parcel/watcher-linux-arm64-glibc": 2.5.0 - "@parcel/watcher-linux-arm64-musl": 2.5.0 - "@parcel/watcher-linux-x64-glibc": 2.5.0 - "@parcel/watcher-linux-x64-musl": 2.5.0 - "@parcel/watcher-win32-arm64": 2.5.0 - "@parcel/watcher-win32-ia32": 2.5.0 - "@parcel/watcher-win32-x64": 2.5.0 - detect-libc: ^1.0.3 + version: 2.5.6 + resolution: "@parcel/watcher@npm:2.5.6" + dependencies: + "@parcel/watcher-android-arm64": 2.5.6 + "@parcel/watcher-darwin-arm64": 2.5.6 + "@parcel/watcher-darwin-x64": 2.5.6 + "@parcel/watcher-freebsd-x64": 2.5.6 + "@parcel/watcher-linux-arm-glibc": 2.5.6 + "@parcel/watcher-linux-arm-musl": 2.5.6 + "@parcel/watcher-linux-arm64-glibc": 2.5.6 + "@parcel/watcher-linux-arm64-musl": 2.5.6 + "@parcel/watcher-linux-x64-glibc": 2.5.6 + "@parcel/watcher-linux-x64-musl": 2.5.6 + "@parcel/watcher-win32-arm64": 2.5.6 + "@parcel/watcher-win32-ia32": 2.5.6 + "@parcel/watcher-win32-x64": 2.5.6 + detect-libc: ^2.0.3 is-glob: ^4.0.3 - micromatch: ^4.0.5 node-addon-api: ^7.0.0 node-gyp: latest + picomatch: ^4.0.3 dependenciesMeta: "@parcel/watcher-android-arm64": optional: true @@ -4214,14 +4164,7 @@ __metadata: optional: true "@parcel/watcher-win32-x64": optional: true - checksum: 253f93c5f443dfbb638df58712df077fe46ff7e01e7c78df0c4ceb001e8f5b31db01eb7ddac3ae4159722c4d1525894cd4ce5be49f5e6c14a3a52cbbf9f41cbf - languageName: node - linkType: hard - -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 6ad6a00fc4f2f2cfc6bff76fb1d88b8ee20bc0601e18ebb01b6d4be583733a860239a521a7fbca73b612e66705078809483549d2b18f370eb346c5155c8e4a0f + checksum: f4f166eaf743630bce0ed1c16db0ac90bd7b5a7e807abf7fe5affb95dbefbb49a6c3a805bfcd7ec82703262b9c7fd0f494a102700e273b1fe66ed9615bb04195 languageName: node linkType: hard @@ -4232,9 +4175,9 @@ __metadata: languageName: node linkType: hard -"@puppeteer/browsers@npm:2.10.13": - version: 2.10.13 - resolution: "@puppeteer/browsers@npm:2.10.13" +"@puppeteer/browsers@npm:2.11.2": + version: 2.11.2 + resolution: "@puppeteer/browsers@npm:2.11.2" dependencies: debug: ^4.4.3 extract-zip: ^2.0.1 @@ -4245,7 +4188,7 @@ __metadata: yargs: ^17.7.2 bin: browsers: lib/cjs/main-cli.js - checksum: d97c6eb4e802fc6aca885754a70530d7c2d52bec0487ea41497654bf5538a0751aae0e19c7318169072114fc2285145261342178e8748bf294793a528077ce14 + checksum: 5411b6e59a2fceed4fa3220d747f5b69f913e46db684655c218dbbc7369b4eedbbc23faee563a731aa6f86a5a389a722e6146b659e78780ba4fd510cf78407a9 languageName: node linkType: hard @@ -4256,9 +4199,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-android-arm-eabi@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.55.1" +"@rollup/rollup-android-arm-eabi@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.57.1" conditions: os=android & cpu=arm languageName: node linkType: hard @@ -4270,9 +4213,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-android-arm64@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-android-arm64@npm:4.55.1" +"@rollup/rollup-android-arm64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-android-arm64@npm:4.57.1" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -4284,9 +4227,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-darwin-arm64@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-darwin-arm64@npm:4.55.1" +"@rollup/rollup-darwin-arm64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-darwin-arm64@npm:4.57.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -4298,9 +4241,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-darwin-x64@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-darwin-x64@npm:4.55.1" +"@rollup/rollup-darwin-x64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-darwin-x64@npm:4.57.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -4312,9 +4255,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-freebsd-arm64@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-freebsd-arm64@npm:4.55.1" +"@rollup/rollup-freebsd-arm64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.57.1" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard @@ -4326,9 +4269,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-freebsd-x64@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-freebsd-x64@npm:4.55.1" +"@rollup/rollup-freebsd-x64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-freebsd-x64@npm:4.57.1" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard @@ -4340,9 +4283,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-arm-gnueabihf@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.55.1" +"@rollup/rollup-linux-arm-gnueabihf@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.57.1" conditions: os=linux & cpu=arm & libc=glibc languageName: node linkType: hard @@ -4354,9 +4297,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-arm-musleabihf@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.55.1" +"@rollup/rollup-linux-arm-musleabihf@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.57.1" conditions: os=linux & cpu=arm & libc=musl languageName: node linkType: hard @@ -4368,9 +4311,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-arm64-gnu@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.55.1" +"@rollup/rollup-linux-arm64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.57.1" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard @@ -4382,9 +4325,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-arm64-musl@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.55.1" +"@rollup/rollup-linux-arm64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.57.1" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard @@ -4396,16 +4339,16 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-loong64-gnu@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.55.1" +"@rollup/rollup-linux-loong64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.57.1" conditions: os=linux & cpu=loong64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-loong64-musl@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-loong64-musl@npm:4.55.1" +"@rollup/rollup-linux-loong64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-loong64-musl@npm:4.57.1" conditions: os=linux & cpu=loong64 & libc=musl languageName: node linkType: hard @@ -4417,16 +4360,16 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-ppc64-gnu@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.55.1" +"@rollup/rollup-linux-ppc64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.57.1" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-ppc64-musl@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-ppc64-musl@npm:4.55.1" +"@rollup/rollup-linux-ppc64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-ppc64-musl@npm:4.57.1" conditions: os=linux & cpu=ppc64 & libc=musl languageName: node linkType: hard @@ -4438,9 +4381,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-gnu@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.55.1" +"@rollup/rollup-linux-riscv64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.57.1" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard @@ -4452,9 +4395,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-musl@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.55.1" +"@rollup/rollup-linux-riscv64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.57.1" conditions: os=linux & cpu=riscv64 & libc=musl languageName: node linkType: hard @@ -4466,9 +4409,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-s390x-gnu@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.55.1" +"@rollup/rollup-linux-s390x-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.57.1" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard @@ -4480,9 +4423,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-x64-gnu@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.55.1" +"@rollup/rollup-linux-x64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.57.1" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard @@ -4494,16 +4437,16 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-x64-musl@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.55.1" +"@rollup/rollup-linux-x64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.57.1" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-openbsd-x64@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-openbsd-x64@npm:4.55.1" +"@rollup/rollup-openbsd-x64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-openbsd-x64@npm:4.57.1" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard @@ -4515,9 +4458,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-openharmony-arm64@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-openharmony-arm64@npm:4.55.1" +"@rollup/rollup-openharmony-arm64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-openharmony-arm64@npm:4.57.1" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard @@ -4529,9 +4472,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-win32-arm64-msvc@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.55.1" +"@rollup/rollup-win32-arm64-msvc@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.57.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -4543,9 +4486,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-win32-ia32-msvc@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.55.1" +"@rollup/rollup-win32-ia32-msvc@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.57.1" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -4557,9 +4500,9 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-win32-x64-gnu@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-win32-x64-gnu@npm:4.55.1" +"@rollup/rollup-win32-x64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-win32-x64-gnu@npm:4.57.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -4571,202 +4514,202 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-win32-x64-msvc@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.55.1" +"@rollup/rollup-win32-x64-msvc@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.57.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@schematics/angular@npm:20.3.14": - version: 20.3.14 - resolution: "@schematics/angular@npm:20.3.14" +"@schematics/angular@npm:20.3.15": + version: 20.3.15 + resolution: "@schematics/angular@npm:20.3.15" dependencies: - "@angular-devkit/core": 20.3.14 - "@angular-devkit/schematics": 20.3.14 + "@angular-devkit/core": 20.3.15 + "@angular-devkit/schematics": 20.3.15 jsonc-parser: 3.3.1 - checksum: 13ab04bd05ec07a2972dca224773dae5040ecd58e4691be81428b87cbffae047f4acd6ea105d953e9190b0d8111747af581293833ee99b976b8449f764cf5fbc + checksum: 93201452eec867879d1f68c3cd6ff583a94fdc5e4362648871fc39e24cba453f2470bfb63d6f02c81002a9350e616795ebf90957da08c1df9fc2347915f66691 languageName: node linkType: hard -"@sentry-internal/browser-utils@npm:10.33.0": - version: 10.33.0 - resolution: "@sentry-internal/browser-utils@npm:10.33.0" +"@sentry-internal/browser-utils@npm:10.38.0": + version: 10.38.0 + resolution: "@sentry-internal/browser-utils@npm:10.38.0" dependencies: - "@sentry/core": 10.33.0 - checksum: 46c548a35baedc111b7f199d495ea717037b0e0f67ba9182d6e00fe1cb73d98d93df0ada4f14e9589c4aff3bf285473039e33cc0b6c444c8d6136a77d935d1c6 + "@sentry/core": 10.38.0 + checksum: 230a78da5ee13ffa077e97982d6b79340dcfbf986f078dbb8a85c77f5133c89b3fecabe510e02e4726e236945bf0c8084b496c153b6916f973442e0528d190c9 languageName: node linkType: hard -"@sentry-internal/feedback@npm:10.33.0": - version: 10.33.0 - resolution: "@sentry-internal/feedback@npm:10.33.0" +"@sentry-internal/feedback@npm:10.38.0": + version: 10.38.0 + resolution: "@sentry-internal/feedback@npm:10.38.0" dependencies: - "@sentry/core": 10.33.0 - checksum: 6bb34af60344b109ec001f709af0f7332d84a4cf3bab9edfb9c3113deea03035156eb44e62c372a5bd6a3430edfdee19370dc7e37a030c26ca1c3e16dfde5e8a + "@sentry/core": 10.38.0 + checksum: 20e07f373ea0eb4cf8f0136a74944584c108609ee3e652dfb02b01b2a75c808318a402605cec58bf8a51e7c4a0074c97edcfd1815434addbf294a1f6cfefdf00 languageName: node linkType: hard -"@sentry-internal/replay-canvas@npm:10.33.0": - version: 10.33.0 - resolution: "@sentry-internal/replay-canvas@npm:10.33.0" +"@sentry-internal/replay-canvas@npm:10.38.0": + version: 10.38.0 + resolution: "@sentry-internal/replay-canvas@npm:10.38.0" dependencies: - "@sentry-internal/replay": 10.33.0 - "@sentry/core": 10.33.0 - checksum: c17acfd2b950641acbe3e841a9013d6ceb3ee2ed6c1f93b05424479d1b9b61c19e0063decf006d391d341ff4344d2e90754a2999c3fb816b073b967831bcce73 + "@sentry-internal/replay": 10.38.0 + "@sentry/core": 10.38.0 + checksum: e163055a60ad44a6a10b03d8ce903c2252f6411cbfce3aaf4c49ec740358ac4746817427ae797590102617e708c4f0dc5af43b43252ada84b951ffd2621b5250 languageName: node linkType: hard -"@sentry-internal/replay@npm:10.33.0": - version: 10.33.0 - resolution: "@sentry-internal/replay@npm:10.33.0" +"@sentry-internal/replay@npm:10.38.0": + version: 10.38.0 + resolution: "@sentry-internal/replay@npm:10.38.0" dependencies: - "@sentry-internal/browser-utils": 10.33.0 - "@sentry/core": 10.33.0 - checksum: eace75ce40fc5d917a5bf436625340fc2b5d5143ff6669edd46f90f1e64e6838846f2488a4246aeb8542ce976a65329ed5e38afc573e20d951cf4be5837ed245 + "@sentry-internal/browser-utils": 10.38.0 + "@sentry/core": 10.38.0 + checksum: 7c92e52ae6af43157cded07e86100f1afd9c939216fed7d3732cd57f9da17c8f4ccba37b5f9658f6f617a9c22eb7d020cf2ab6e35261daee49fdfe5e8c2fda35 languageName: node linkType: hard -"@sentry-internal/rrdom@npm:2.31.0": - version: 2.31.0 - resolution: "@sentry-internal/rrdom@npm:2.31.0" +"@sentry-internal/rrdom@npm:2.40.0": + version: 2.40.0 + resolution: "@sentry-internal/rrdom@npm:2.40.0" dependencies: - "@sentry-internal/rrweb-snapshot": 2.31.0 - checksum: 716dbb2d2c2667cf882d72b4e5fd1f3c20a569bbbddc606c52f88ffd0cb920292cfb196d3d8c326e62ff72df1d4e50d2d58d41599d80825cc479866772611fda + "@sentry-internal/rrweb-snapshot": 2.40.0 + checksum: 68563239a4fb44f51225a179d3a9e56dd318ab6dc3a407441ec58fe17b1d3639bf22aa894d45bff016f9b721b58fed837f844e9596bc987e3f9a2471ef8bb824 languageName: node linkType: hard -"@sentry-internal/rrweb-snapshot@npm:2.31.0": - version: 2.31.0 - resolution: "@sentry-internal/rrweb-snapshot@npm:2.31.0" - checksum: ef0b5ee01ccbf3c8df7c2861710df0928c33f7c4c7bcd47d6b410fbcf703f01dcb24dad284472ac4d6ef02eb10acca8e94ed5e8724d184e336467e7cdf2f1c6d +"@sentry-internal/rrweb-snapshot@npm:2.40.0": + version: 2.40.0 + resolution: "@sentry-internal/rrweb-snapshot@npm:2.40.0" + checksum: 6db46d8bae13104e9dea77e83be091173e97cf34948759b5a3fe7513995602596a107579bade1d1b9960349d79d98b1a4a983eeed688814197a76527a7dbb932 languageName: node linkType: hard -"@sentry-internal/rrweb-types@npm:2.31.0": - version: 2.31.0 - resolution: "@sentry-internal/rrweb-types@npm:2.31.0" +"@sentry-internal/rrweb-types@npm:2.40.0": + version: 2.40.0 + resolution: "@sentry-internal/rrweb-types@npm:2.40.0" dependencies: - "@sentry-internal/rrweb-snapshot": 2.31.0 + "@sentry-internal/rrweb-snapshot": 2.40.0 "@types/css-font-loading-module": 0.0.7 - checksum: 5e70e8a1d78337f71cccac0a967b282b7c05cb590e8b1a997e28483faa4cc4746397fde3be4a2ab380d0f59e4ca7b65284b018ae6ddf67028b2fce4a9a8788ce + checksum: 139d6e045f6a409cfdb7348ca036e52649f33d0defd373deb9c197dce1ec31d2d41cc3d71fe399a202297dbf648400a393b814e4b7e192d22b3e8c5ea8f237da languageName: node linkType: hard "@sentry-internal/rrweb@npm:^2.16.0": - version: 2.31.0 - resolution: "@sentry-internal/rrweb@npm:2.31.0" + version: 2.40.0 + resolution: "@sentry-internal/rrweb@npm:2.40.0" dependencies: - "@sentry-internal/rrdom": 2.31.0 - "@sentry-internal/rrweb-snapshot": 2.31.0 - "@sentry-internal/rrweb-types": 2.31.0 + "@sentry-internal/rrdom": 2.40.0 + "@sentry-internal/rrweb-snapshot": 2.40.0 + "@sentry-internal/rrweb-types": 2.40.0 "@types/css-font-loading-module": 0.0.7 "@xstate/fsm": ^1.4.0 base64-arraybuffer: ^1.0.1 fflate: ^0.4.4 mitt: ^3.0.0 - checksum: 03fcf928b275d30366f126f6c78fd13506b9b3242b89b24d9c0095acfb6a513f633a58b63baab0aa9b1a6654f536ab2c4b802de0f3faecc04bb5f0d0dbbafd2a + checksum: c5e1524e34261af20524e25f38c2b6ce1bd40a79b5722fd840a10da9cad024e827543b2cbeb6078c0efb7fd9b64ab574603f94fe11a21b4f2347c3cdc9bc4819 languageName: node linkType: hard "@sentry/angular@npm:^10.33.0": - version: 10.33.0 - resolution: "@sentry/angular@npm:10.33.0" + version: 10.38.0 + resolution: "@sentry/angular@npm:10.38.0" dependencies: - "@sentry/browser": 10.33.0 - "@sentry/core": 10.33.0 + "@sentry/browser": 10.38.0 + "@sentry/core": 10.38.0 tslib: ^2.4.1 peerDependencies: "@angular/common": ">= 14.x <= 21.x" "@angular/core": ">= 14.x <= 21.x" "@angular/router": ">= 14.x <= 21.x" rxjs: ^6.5.5 || ^7.x - checksum: 5b24bdcf4687857bd2111c7cbb5cb440b94cc662cbe35ec25b1caf34dfcef4963a8346a1f675a1b37a1ae81a275fbb120b9a5c327b0ec0c7a0c554446af69f07 + checksum: c22c8304ad51276876d9c5f86caf377133be163d3a259c564816a9e966ceef33593e8ccb99be748e7feda2f37da721073172651ad7be478f59fd73afaacb41e1 languageName: node linkType: hard -"@sentry/browser@npm:10.33.0": - version: 10.33.0 - resolution: "@sentry/browser@npm:10.33.0" +"@sentry/browser@npm:10.38.0": + version: 10.38.0 + resolution: "@sentry/browser@npm:10.38.0" dependencies: - "@sentry-internal/browser-utils": 10.33.0 - "@sentry-internal/feedback": 10.33.0 - "@sentry-internal/replay": 10.33.0 - "@sentry-internal/replay-canvas": 10.33.0 - "@sentry/core": 10.33.0 - checksum: 92d9c98671fc7783b8a787f22706a36545166871b752704df2be4fbb0161dd7025567ccd0f510b592f77162b4f26b51b519bd3a3aa40ffe5d4b8197d5aab7d33 + "@sentry-internal/browser-utils": 10.38.0 + "@sentry-internal/feedback": 10.38.0 + "@sentry-internal/replay": 10.38.0 + "@sentry-internal/replay-canvas": 10.38.0 + "@sentry/core": 10.38.0 + checksum: 83a58f802de60b7e65b818696e71d36832e7a1bf38bf79b59d0fa14b2f22774d4f500c86a6ba7911e5aa5603f5b2039d5c47fbc9778733552019a9e97d25fbac languageName: node linkType: hard -"@sentry/core@npm:10.33.0": - version: 10.33.0 - resolution: "@sentry/core@npm:10.33.0" - checksum: 25eb49f6f4277889e2823e1a09c5ae1a4c6d1361365d31fecc7ead630dd9304fab80c71aad46ac001158cfdbd11852668f75384b86186fd0b0431b3ff00ace95 +"@sentry/core@npm:10.38.0": + version: 10.38.0 + resolution: "@sentry/core@npm:10.38.0" + checksum: 34da7144b72645ec2604670a912f4ad4ac16cbf5334f95316e103d0bce4934acebdb8e48750dbf609c5e8f16c004a1d097127c111cb6d8f612595c4be398ceaa languageName: node linkType: hard -"@sigstore/bundle@npm:^3.0.0": - version: 3.0.0 - resolution: "@sigstore/bundle@npm:3.0.0" +"@sigstore/bundle@npm:^4.0.0": + version: 4.0.0 + resolution: "@sigstore/bundle@npm:4.0.0" dependencies: - "@sigstore/protobuf-specs": ^0.3.2 - checksum: cef110acd000dea0cbdf01f48e979ea574e4f29439d2367bad255dcbe7ec185d66873f7c2428bbe109dffd944a50786e9eefc802f008d464dc683c1bbc8fb2d5 + "@sigstore/protobuf-specs": ^0.5.0 + checksum: 1a7ca1722c31ba42af0d33a14114224a90e61061eab4248f2ba8241430dc6dfca3b59e1878c7ad3693d6938c87aeedb2dff4819a2261b3d00b751240e2044eb9 languageName: node linkType: hard -"@sigstore/core@npm:^2.0.0": - version: 2.0.0 - resolution: "@sigstore/core@npm:2.0.0" - checksum: fd21df6ce574ef8fed855955ce864523368bdca8202ed9d90f2b4822f4889315a23f52eef72cbf09534af669329c8affdd36a3615c9598eb9311a4cc22f3f21a +"@sigstore/core@npm:^3.1.0": + version: 3.1.0 + resolution: "@sigstore/core@npm:3.1.0" + checksum: 09e5d9c800821a10a8b0deeadb05376a536b1a0134044d823f5a7184f487c1a2874a6764d7f2e71108cfb2376faa7beb9cb9ba857daf27dc677455302b2738c0 languageName: node linkType: hard -"@sigstore/protobuf-specs@npm:^0.3.2": - version: 0.3.2 - resolution: "@sigstore/protobuf-specs@npm:0.3.2" - checksum: 677b67eb4c3128432169fa168a5daae343a0242ffada3811bfde844644ac2eae0127cbf39349ed59e1a4edd14064416285251abb6acb260b6e3e9b6b40705c13 +"@sigstore/protobuf-specs@npm:^0.5.0": + version: 0.5.0 + resolution: "@sigstore/protobuf-specs@npm:0.5.0" + checksum: bfb34ce233f893635d6a757c11bde23cabfa173b5f7c8bc28e02181ca23c4eeb9272b507bdf5543a8254697acc65b9781d714397edeb09c6f3fa781857e9b9d5 languageName: node linkType: hard -"@sigstore/sign@npm:^3.0.0": - version: 3.0.0 - resolution: "@sigstore/sign@npm:3.0.0" +"@sigstore/sign@npm:^4.1.0": + version: 4.1.0 + resolution: "@sigstore/sign@npm:4.1.0" dependencies: - "@sigstore/bundle": ^3.0.0 - "@sigstore/core": ^2.0.0 - "@sigstore/protobuf-specs": ^0.3.2 - make-fetch-happen: ^14.0.1 - proc-log: ^5.0.0 + "@sigstore/bundle": ^4.0.0 + "@sigstore/core": ^3.1.0 + "@sigstore/protobuf-specs": ^0.5.0 + make-fetch-happen: ^15.0.3 + proc-log: ^6.1.0 promise-retry: ^2.0.1 - checksum: 8a7523ef128808c0b962757e6451269ed966b56b5487c6e2b0708c3703e70d83d70911d0731cbc35e926400fbcf1ecb5187cf82aec3334d18a72e49e78f79330 + checksum: 24c3b66a391142ffb65dc5b632c588455b1b9bafb4204cad2bd1e87985a712a5b11115cca6bf5d7de26a55488a8caf97575f9fd33babdb6d470009a0767a9461 languageName: node linkType: hard -"@sigstore/tuf@npm:^3.0.0": - version: 3.0.0 - resolution: "@sigstore/tuf@npm:3.0.0" +"@sigstore/tuf@npm:^4.0.1": + version: 4.0.1 + resolution: "@sigstore/tuf@npm:4.0.1" dependencies: - "@sigstore/protobuf-specs": ^0.3.2 - tuf-js: ^3.0.1 - checksum: 184b84642abb8cad377a845892d1039dfd29b4275f324f1987ed4153689887adddfe5172bfb7f1851f3f915c967f78e51d40e7efb6877a5ae61313a3b44af754 + "@sigstore/protobuf-specs": ^0.5.0 + tuf-js: ^4.1.0 + checksum: 380604538bfdbcfd14ec2495e0c065c93ffa1d5e52d0a314bf2f89d8e5a999f22ce74425acde8195808126c29880a6fcd88837aa5ec485ebfb347dbb5a9d0634 languageName: node linkType: hard -"@sigstore/verify@npm:^2.0.0": - version: 2.0.0 - resolution: "@sigstore/verify@npm:2.0.0" +"@sigstore/verify@npm:^3.1.0": + version: 3.1.0 + resolution: "@sigstore/verify@npm:3.1.0" dependencies: - "@sigstore/bundle": ^3.0.0 - "@sigstore/core": ^2.0.0 - "@sigstore/protobuf-specs": ^0.3.2 - checksum: 987d3d927f3be11f3a50287b4a30aff1abd622b59cbc233f633b32bf5a331c8b7da5624b27b01aa0213da4e14e28def23e43f353d95033a4a3b3f8b44a59564b + "@sigstore/bundle": ^4.0.0 + "@sigstore/core": ^3.1.0 + "@sigstore/protobuf-specs": ^0.5.0 + checksum: fdb1e008fe346eeaf31ee58bfb5b7e1db1b292fe14f3eaf001e2d67eb3aa3af1637c2e17d87ceaf62d5fcee599a0ec30198480c91559b694bfe963e81d09879e languageName: node linkType: hard "@stripe/stripe-js@npm:^5.3.0": - version: 5.3.0 - resolution: "@stripe/stripe-js@npm:5.3.0" - checksum: 49eb7926de2aa493097ee2fef8c34290c247cd8b0749ccc20a0d41be9a87c97cdda0a3476ff7637cc218b45310ed7312d57c43aa0e7553b15e1cfecea19f7c50 + version: 5.10.0 + resolution: "@stripe/stripe-js@npm:5.10.0" + checksum: e3e0025dae8b406eec981fb41100dcf2d30bfaec63411001e1af78b0495497ca18f3a95869e6ae0346264072fe763a752f5d7424af9378ff441ea85eb572fcd3 languageName: node linkType: hard @@ -4803,9 +4746,9 @@ __metadata: linkType: hard "@tsconfig/node10@npm:^1.0.7": - version: 1.0.11 - resolution: "@tsconfig/node10@npm:1.0.11" - checksum: 51fe47d55fe1b80ec35e6e5ed30a13665fd3a531945350aa74a14a1e82875fb60b350c2f2a5e72a64831b1b6bc02acb6760c30b3738b54954ec2dea82db7a267 + version: 1.0.12 + resolution: "@tsconfig/node10@npm:1.0.12" + checksum: 27e2f989dbb20f773aa121b609a5361a473b7047ff286fce7c851e61f5eec0c74f0bdb38d5bd69c8a06f17e60e9530188f2219b1cbeabeac91f0a5fd348eac2a languageName: node linkType: hard @@ -4837,13 +4780,13 @@ __metadata: languageName: node linkType: hard -"@tufjs/models@npm:3.0.1": - version: 3.0.1 - resolution: "@tufjs/models@npm:3.0.1" +"@tufjs/models@npm:4.1.0": + version: 4.1.0 + resolution: "@tufjs/models@npm:4.1.0" dependencies: "@tufjs/canonical-json": 2.0.0 - minimatch: ^9.0.5 - checksum: 95b179bc09e5a0b6dfc9e7001e15882e863e034bf41e0502e89f2fa82cb3f6d5bd9edaefd2baf2a7f515abdb521127adf771e8bbe66f3e7f212e3b777ae993f5 + minimatch: ^10.1.1 + checksum: 7707ffd1a51e0f9c9d67dcda3f74e23bcbe46edcb22a95983f8fccd59385d8115b0c375280521c05dff633a1e9bfac2d425a2a582a5d2c1b0c91f2a03aa7798d languageName: node linkType: hard @@ -4864,12 +4807,12 @@ __metadata: linkType: hard "@types/body-parser@npm:*": - version: 1.19.5 - resolution: "@types/body-parser@npm:1.19.5" + version: 1.19.6 + resolution: "@types/body-parser@npm:1.19.6" dependencies: "@types/connect": "*" "@types/node": "*" - checksum: 1e251118c4b2f61029cc43b0dc028495f2d1957fe8ee49a707fb940f86a9bd2f9754230805598278fe99958b49e9b7e66eec8ef6a50ab5c1f6b93e1ba2aaba82 + checksum: 33041e88eae00af2cfa0827e951e5f1751eafab2a8b6fce06cd89ef368a988907996436b1325180edaeddd1c0c7d0d0d4c20a6c9ff294a91e0039a9db9e9b658 languageName: node linkType: hard @@ -4919,9 +4862,9 @@ __metadata: linkType: hard "@types/d3-array@npm:*": - version: 3.2.1 - resolution: "@types/d3-array@npm:3.2.1" - checksum: 8a41cee0969e53bab3f56cc15c4e6c9d76868d6daecb2b7d8c9ce71e0ececccc5a8239697cc52dadf5c665f287426de5c8ef31a49e7ad0f36e8846889a383df4 + version: 3.2.2 + resolution: "@types/d3-array@npm:3.2.2" + checksum: 72e8e2abe0911cb431d6f3fe0a1f71b915356b679d4d9c826f52941bb30210c0fe8299dde066b08d9986754c620f031b13b13ab6dfc60d404eceab66a075dd5d languageName: node linkType: hard @@ -4975,9 +4918,9 @@ __metadata: linkType: hard "@types/d3-dispatch@npm:*": - version: 3.0.6 - resolution: "@types/d3-dispatch@npm:3.0.6" - checksum: f82076c7d205885480d363c92c19b8e0d6b9e529a3a78ce772f96a7cc4cce01f7941141f148828337035fac9676b13e7440565530491d560fdf12e562cb56573 + version: 3.0.7 + resolution: "@types/d3-dispatch@npm:3.0.7" + checksum: ce7ab5a7d5c64aacf563797c0c61f3862b9ff687cb35470fe462219f09e402185646f51707339beede616586d92ded6974c3958dbeb15e35a85b1ecfafdf13a8 languageName: node linkType: hard @@ -5053,9 +4996,9 @@ __metadata: linkType: hard "@types/d3-path@npm:*": - version: 3.1.0 - resolution: "@types/d3-path@npm:3.1.0" - checksum: 1e81b56ed33ba1ac954a8c42c78c3fcf2716927fe5d01b2003591193ad3b639572a3dfcedd9bf78b6b73215a5cfb01cede8f25c936e95ac18fbe3858f9b62f5c + version: 3.1.1 + resolution: "@types/d3-path@npm:3.1.1" + checksum: fee8f6b0d3b28a3611c7d7fda3bf2f79392ded266f54b03a220f205c42117644bdcd33dcbf4853da3cca02229f1c669d2a60d5d297a24ce459ba8271ccb26c03 languageName: node linkType: hard @@ -5088,11 +5031,11 @@ __metadata: linkType: hard "@types/d3-scale@npm:*": - version: 4.0.8 - resolution: "@types/d3-scale@npm:4.0.8" + version: 4.0.9 + resolution: "@types/d3-scale@npm:4.0.9" dependencies: "@types/d3-time": "*" - checksum: 3b1906da895564f73bb3d0415033d9a8aefe7c4f516f970176d5b2ff7a417bd27ae98486e9a9aa0472001dc9885a9204279a1973a985553bdb3ee9bbc1b94018 + checksum: c44265a38e538983686b1b8d159abfb4e81c09b33316f3a68f0f372d38400fa950ad531644d25230cc7b48ea5adb50270fc54823f088979ade62dcd0225f7aa3 languageName: node linkType: hard @@ -5104,11 +5047,11 @@ __metadata: linkType: hard "@types/d3-shape@npm:*": - version: 3.1.6 - resolution: "@types/d3-shape@npm:3.1.6" + version: 3.1.8 + resolution: "@types/d3-shape@npm:3.1.8" dependencies: "@types/d3-path": "*" - checksum: bd765be021019c43c8dca066a798a1de28a051d1213db6ca25f76c9e577da7ec40a592e3bda7628383ab48cb87164fe60b95eb5ec23761b2012bd0adb30c549a + checksum: 659d51882dccc85d24817bdbcd50589212d12e24eb2aad19bae073665ed25443026e120966faa8523f0412f8a30f7c16002499cea3eb87d25b3011e0ee42e6a2 languageName: node linkType: hard @@ -5217,14 +5160,7 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:*": - version: 1.0.6 - resolution: "@types/estree@npm:1.0.6" - checksum: 8825d6e729e16445d9a1dd2fb1db2edc5ed400799064cd4d028150701031af012ba30d6d03fe9df40f4d7a437d0de6d2b256020152b7b09bde9f2e420afdffd9 - languageName: node - linkType: hard - -"@types/estree@npm:1.0.8, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.8": +"@types/estree@npm:*, @types/estree@npm:1.0.8, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.8": version: 1.0.8 resolution: "@types/estree@npm:1.0.8" checksum: bd93e2e415b6f182ec4da1074e1f36c480f1d26add3e696d54fb30c09bc470897e41361c8fd957bf0985024f8fbf1e6e2aff977d79352ef7eb93a5c6dcff6c11 @@ -5232,80 +5168,79 @@ __metadata: linkType: hard "@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^5.0.0": - version: 5.0.2 - resolution: "@types/express-serve-static-core@npm:5.0.2" + version: 5.1.1 + resolution: "@types/express-serve-static-core@npm:5.1.1" dependencies: "@types/node": "*" "@types/qs": "*" "@types/range-parser": "*" "@types/send": "*" - checksum: 841229b63801b334729e56ec04b5023e084e2962d61dddc95b3508e2fc821e8550bd69c074b6cb0a1c57147eb324c4dc543103d0827e34077f7eb6d230d08a8f + checksum: 6720802b89e7e0542c678f5176f05e0a0109ae79a7aeeb46fc5d15d733416662e0d67ed417df615f684c8006dba20f051d1cfeb4d1d2d8a78e3624a15c6df9a3 languageName: node linkType: hard "@types/express-serve-static-core@npm:^4.17.21, @types/express-serve-static-core@npm:^4.17.33": - version: 4.19.6 - resolution: "@types/express-serve-static-core@npm:4.19.6" + version: 4.19.8 + resolution: "@types/express-serve-static-core@npm:4.19.8" dependencies: "@types/node": "*" "@types/qs": "*" "@types/range-parser": "*" "@types/send": "*" - checksum: b0576eddc2d25ccdf10e68ba09598b87a4d7b2ad04a81dc847cb39fe56beb0b6a5cc017b1e00aa0060cb3b38e700384ce96d291a116a0f1e54895564a104aae9 + checksum: 7bb52381a302de5af5af0f1cc8aa8144cdd4c244a7bbd8f989fb06b6a21368481ad52ddcb989e17f818f1cb4ec65c296e2e851b07335bea5ad2124eff80812d7 languageName: node linkType: hard "@types/express@npm:*": - version: 5.0.0 - resolution: "@types/express@npm:5.0.0" + version: 5.0.6 + resolution: "@types/express@npm:5.0.6" dependencies: "@types/body-parser": "*" "@types/express-serve-static-core": ^5.0.0 - "@types/qs": "*" - "@types/serve-static": "*" - checksum: ef68d8e2b7593c930093b1e79bf4df15413773508c9acd6a1a933ed7017f2a4892a8d128b2222d7eab9a3fa43181067a378c2600d9258bd7ae917f170e962df4 + "@types/serve-static": ^2 + checksum: da2cc3de1b1a4d7f20ed3fb6f0a8ee08e99feb3c2eb5a8d643db77017d8d0e70fee9e95da38a73f51bcdf5eda3bb6435073c0271dc04fb16fda92e55daf911fa languageName: node linkType: hard "@types/express@npm:^4.17.21": - version: 4.17.21 - resolution: "@types/express@npm:4.17.21" + version: 4.17.25 + resolution: "@types/express@npm:4.17.25" dependencies: "@types/body-parser": "*" "@types/express-serve-static-core": ^4.17.33 "@types/qs": "*" - "@types/serve-static": "*" - checksum: fb238298630370a7392c7abdc80f495ae6c716723e114705d7e3fb67e3850b3859bbfd29391463a3fb8c0b32051847935933d99e719c0478710f8098ee7091c5 + "@types/serve-static": ^1 + checksum: 285d16008489d37b2be03e2e050bcf201d5d6ed9278ca13619d9029efd2055b192b2445f769116f716cfcf53d9d799a03f4e76199af9cea0ea3dee3d88595931 languageName: node linkType: hard "@types/geojson@npm:*": - version: 7946.0.15 - resolution: "@types/geojson@npm:7946.0.15" - checksum: 226d7ab59540632b19f7889c76c4c586a5104c18c43a81f32974aa035eafe557f86bd5a79ca5568bb63cbe5bfa9014c8e9a29cb0bb3d2f0bd71b0cc13ad8ccb3 + version: 7946.0.16 + resolution: "@types/geojson@npm:7946.0.16" + checksum: d66e5e023f43b3e7121448117af1930af7d06410a32a585a8bc9c6bb5d97e0d656cd93d99e31fa432976c32e98d4b780f82bf1fd1acd20ccf952eb6b8e39edf2 languageName: node linkType: hard "@types/google-one-tap@npm:^1.2.6": - version: 1.2.6 - resolution: "@types/google-one-tap@npm:1.2.6" - checksum: 7439aa51d79ad07e587087887ce86f0932222f4fa5e24e4a62fce5d8bf17ba663441d2f69da97d55056b82ed11f0474591d8c6a508232dd0a8f61b42ecc036ba + version: 1.2.7 + resolution: "@types/google-one-tap@npm:1.2.7" + checksum: 0025e6c49ec8392d7f3af4874bda99e1ec14e73cf698393fba62c1f4286cbd95d7987bf008dc631ca3b768bc26459531b5675ddc1af78075dc471637169e0a5b languageName: node linkType: hard "@types/http-errors@npm:*": - version: 2.0.4 - resolution: "@types/http-errors@npm:2.0.4" - checksum: 1f3d7c3b32c7524811a45690881736b3ef741bf9849ae03d32ad1ab7062608454b150a4e7f1351f83d26a418b2d65af9bdc06198f1c079d75578282884c4e8e3 + version: 2.0.5 + resolution: "@types/http-errors@npm:2.0.5" + checksum: a88da669366bc483e8f3b3eb3d34ada5f8d13eeeef851b1204d77e2ba6fc42aba4566d877cca5c095204a3f4349b87fe397e3e21288837bdd945dd514120755b languageName: node linkType: hard "@types/http-proxy@npm:^1.17.15, @types/http-proxy@npm:^1.17.8": - version: 1.17.15 - resolution: "@types/http-proxy@npm:1.17.15" + version: 1.17.17 + resolution: "@types/http-proxy@npm:1.17.17" dependencies: "@types/node": "*" - checksum: d96eaf4e22232b587b46256b89c20525c453216684481015cf50fb385b0b319b883749ccb77dee9af57d107e8440cdacd56f4234f65176d317e9777077ff5bf3 + checksum: 7231460dc06c109447b21c125a60662872b9c2e902efd12c47902b8ad75caded19678fa3115f6b9ce06b94d2f46d697be572e848c52da558f4f1ee88ff18a2e0 languageName: node linkType: hard @@ -5317,9 +5252,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.17.13": - version: 4.17.13 - resolution: "@types/lodash@npm:4.17.13" - checksum: d0bf8fbd950be71946e0076b30fd40d492293baea75f05931b6b5b906fd62583708c6229abdb95b30205ad24ce1ed2f48bc9d419364f682320edd03405cc0c7e + version: 4.17.23 + resolution: "@types/lodash@npm:4.17.23" + checksum: 38638641526759688656b9930c0a2714536bdc2b84d5a2d4dc4b7825ba39a74ceedcc9971a9c7511189dad987426135b647616e4f49f2d67893617bdb7c85f84 languageName: node linkType: hard @@ -5331,27 +5266,36 @@ __metadata: linkType: hard "@types/node-forge@npm:^1.3.0": - version: 1.3.11 - resolution: "@types/node-forge@npm:1.3.11" + version: 1.3.14 + resolution: "@types/node-forge@npm:1.3.14" dependencies: "@types/node": "*" - checksum: 1e86bd55b92a492eaafd75f6d01f31e7d86a5cdadd0c6bcdc0b1df4103b7f99bb75b832efd5217c7ddda5c781095dc086a868e20b9de00f5a427ddad4c296cd5 + checksum: ff621803390e723e56b289a89fca3a06f9f8b438add1b843203a0f64bcbc7ac03d457136b3c15010b5bc89d81f57b35f62964e6e980f6290597bb21b4463c009 + languageName: node + linkType: hard + +"@types/node@npm:*": + version: 25.2.0 + resolution: "@types/node@npm:25.2.0" + dependencies: + undici-types: ~7.16.0 + checksum: 83aca6a518cac06e1e34a0735b800f8814c78182d15fb99f2329cc9ef1c7242f478916366752305e9000c8ce869b3bf718e9bc10ff1b7e1c1d595a0cb999570a languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^22.10.2": - version: 22.10.2 - resolution: "@types/node@npm:22.10.2" +"@types/node@npm:^22.10.2": + version: 22.19.7 + resolution: "@types/node@npm:22.19.7" dependencies: - undici-types: ~6.20.0 - checksum: b22401e6e7d1484e437d802c72f5560e18100b1257b9ad0574d6fe05bebe4dbcb620ea68627d1f1406775070d29ace8b6b51f57e7b1c7b8bafafe6da7f29c843 + undici-types: ~6.21.0 + checksum: 3feba083e0e29d58dfceec726de19cb246616c1af5bed8d779ac2b6ee92662016ad2ead44f04279143b459741300c52883e759d68f42d75e372da247b38eebe9 languageName: node linkType: hard "@types/qs@npm:*": - version: 6.9.17 - resolution: "@types/qs@npm:6.9.17" - checksum: fc3beda0be70e820ddabaa361e8dfec5e09b482b8f6cf1515615479a027dd06cd5ba0ffbd612b654c2605523f45f484c8905a475623d6cd0c4cadcf5d0c517f5 + version: 6.14.0 + resolution: "@types/qs@npm:6.14.0" + checksum: 1909205514d22b3cbc7c2314e2bd8056d5f05dfb21cf4377f0730ee5e338ea19957c41735d5e4806c746176563f50005bbab602d8358432e25d900bdf4970826 languageName: node linkType: hard @@ -5370,12 +5314,21 @@ __metadata: linkType: hard "@types/send@npm:*": - version: 0.17.4 - resolution: "@types/send@npm:0.17.4" + version: 1.2.1 + resolution: "@types/send@npm:1.2.1" + dependencies: + "@types/node": "*" + checksum: 3b8388edeec77ae62f7bbc384c98ca06140614e4ef34fc04b35824f19937f472f8ff3785e83570e0d40e6d7c934c015d4831c82a74a1ade0d9676720835702c5 + languageName: node + linkType: hard + +"@types/send@npm:<1": + version: 0.17.6 + resolution: "@types/send@npm:0.17.6" dependencies: "@types/mime": ^1 "@types/node": "*" - checksum: cf4db48251bbb03cd6452b4de6e8e09e2d75390a92fd798eca4a803df06444adc94ed050246c94c7ed46fb97be1f63607f0e1f13c3ce83d71788b3e08640e5e0 + checksum: 5bd287f1357380963eb4b12daef5c8982f52a3269308ff3414304074d4ad7f05fe466f2cb476f54798096877ad3c5343692978776bd674b25261ecbeab87640f languageName: node linkType: hard @@ -5388,14 +5341,24 @@ __metadata: languageName: node linkType: hard -"@types/serve-static@npm:*, @types/serve-static@npm:^1.15.5": - version: 1.15.7 - resolution: "@types/serve-static@npm:1.15.7" +"@types/serve-static@npm:^1, @types/serve-static@npm:^1.15.5": + version: 1.15.10 + resolution: "@types/serve-static@npm:1.15.10" dependencies: "@types/http-errors": "*" "@types/node": "*" - "@types/send": "*" - checksum: bbbf00dbd84719da2250a462270dc68964006e8d62f41fe3741abd94504ba3688f420a49afb2b7478921a1544d3793183ffa097c5724167da777f4e0c7f1a7d6 + "@types/send": <1 + checksum: f216eef2aaf2c8eff09f431c420c5c2989eaf0dfc15d106db9fb64c14577a4059af24fb0ae2eba7984d6360950c8cbc1fb52f65608106477729d251481bc96fe + languageName: node + linkType: hard + +"@types/serve-static@npm:^2": + version: 2.2.0 + resolution: "@types/serve-static@npm:2.2.0" + dependencies: + "@types/http-errors": "*" + "@types/node": "*" + checksum: 0ad152ae2851cbe6c9381d0eca5fff8e6ff56afc0e03099efa88712c00318f52d8b01000be391375dcb2dbd912a54dacfc67ff36bae636a61570d74feba559b7 languageName: node linkType: hard @@ -5416,11 +5379,11 @@ __metadata: linkType: hard "@types/ws@npm:^8.5.10": - version: 8.5.13 - resolution: "@types/ws@npm:8.5.13" + version: 8.18.1 + resolution: "@types/ws@npm:8.18.1" dependencies: "@types/node": "*" - checksum: f17023ce7b89c6124249c90211803a4aaa02886e12bc2d0d2cd47fa665eeb058db4d871ce4397d8e423f6beea97dd56835dd3fdbb921030fe4d887601e37d609 + checksum: 0331b14cde388e2805af66cad3e3f51857db8e68ed91e5b99750915e96fe7572e58296dc99999331bbcf08f0ff00a227a0bb214e991f53c2a5aca7b0e71173fa languageName: node linkType: hard @@ -5747,10 +5710,10 @@ __metadata: languageName: node linkType: hard -"abbrev@npm:^2.0.0": - version: 2.0.0 - resolution: "abbrev@npm:2.0.0" - checksum: 0e994ad2aa6575f94670d8a2149afe94465de9cedaaaac364e7fb43a40c3691c980ff74899f682f4ca58fa96b4cbd7421a015d3a6defe43a442117d7821a2f36 +"abbrev@npm:^4.0.0": + version: 4.0.0 + resolution: "abbrev@npm:4.0.0" + checksum: d0344b63d28e763f259b4898c41bdc92c08e9d06d0da5617d0bbe4d78244e46daea88c510a2f9472af59b031d9060ec1a999653144e793fd029a59dae2f56dc8 languageName: node linkType: hard @@ -5764,7 +5727,7 @@ __metadata: languageName: node linkType: hard -"accepts@npm:~1.3.4, accepts@npm:~1.3.8": +"accepts@npm:~1.3.8": version: 1.3.8 resolution: "accepts@npm:1.3.8" dependencies: @@ -5792,16 +5755,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.11.0, acorn@npm:^8.14.0, acorn@npm:^8.4.1, acorn@npm:^8.8.2": - version: 8.14.0 - resolution: "acorn@npm:8.14.0" - bin: - acorn: bin/acorn - checksum: 8755074ba55fff94e84e81c72f1013c2d9c78e973c31231c8ae505a5f966859baf654bddd75046bffd73ce816b149298977fff5077a3033dedba0ae2aad152d4 - languageName: node - linkType: hard - -"acorn@npm:^8.15.0": +"acorn@npm:^8.11.0, acorn@npm:^8.14.0, acorn@npm:^8.15.0, acorn@npm:^8.4.1": version: 8.15.0 resolution: "acorn@npm:8.15.0" bin: @@ -5821,9 +5775,9 @@ __metadata: linkType: hard "agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": - version: 7.1.3 - resolution: "agent-base@npm:7.1.3" - checksum: 87bb7ee54f5ecf0ccbfcba0b07473885c43ecd76cb29a8db17d6137a19d9f9cd443a2a7c5fd8a3f24d58ad8145f9eb49116344a66b107e1aeab82cf2383f4753 + version: 7.1.4 + resolution: "agent-base@npm:7.1.4" + checksum: 86a7f542af277cfbd77dd61e7df8422f90bac512953709003a1c530171a9d019d072e2400eab2b59f84b49ab9dd237be44315ca663ac73e82b3922d10ea5eafa languageName: node linkType: hard @@ -5949,11 +5903,11 @@ __metadata: linkType: hard "ansi-escapes@npm:^7.0.0": - version: 7.0.0 - resolution: "ansi-escapes@npm:7.0.0" + version: 7.2.0 + resolution: "ansi-escapes@npm:7.2.0" dependencies: environment: ^1.0.0 - checksum: 19baa61e68d1998c03b3b8bd023653a6c2667f0ed6caa9a00780ffd6f0a14f4a6563c57a38b3c0aba71bd704cd49c4c8df41be60bd81c957409f91e9dd49051f + checksum: d490871d4107dc6d4b0f2d0eaddbe3e4681d584c58495f06fe2908f2707bbaaf54825f485c5a6ce14c2d2a731fa382b18d7235a102db69aeff5dd9461397cb44 languageName: node linkType: hard @@ -5974,9 +5928,9 @@ __metadata: linkType: hard "ansi-regex@npm:^6.0.1": - version: 6.1.0 - resolution: "ansi-regex@npm:6.1.0" - checksum: 495834a53b0856c02acd40446f7130cb0f8284f4a39afdab20d5dc42b2e198b1196119fe887beed8f9055c4ff2055e3b2f6d4641d0be018cdfb64fedf6fc1aac + version: 6.2.2 + resolution: "ansi-regex@npm:6.2.2" + checksum: 9b17ce2c6daecc75bcd5966b9ad672c23b184dc3ed9bf3c98a0702f0d2f736c15c10d461913568f2cf527a5e64291c7473358885dd493305c84a1cfed66ba94f languageName: node linkType: hard @@ -5996,17 +5950,10 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^6.0.0, ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: ef940f2f0ced1a6347398da88a91da7930c33ecac3c77b72c5905f8b8fe402c52e6fde304ff5347f616e27a742da3f1dc76de98f6866c69251ad0b07a66776d9 - languageName: node - linkType: hard - -"any-promise@npm:^1.0.0": - version: 1.3.0 - resolution: "any-promise@npm:1.3.0" - checksum: 0ee8a9bdbe882c90464d75d1f55cf027f5458650c4bd1f0467e65aec38ccccda07ca5844969ee77ed46d04e7dded3eaceb027e8d32f385688523fe305fa7e1de +"ansi-styles@npm:^6.0.0, ansi-styles@npm:^6.2.1": + version: 6.2.3 + resolution: "ansi-styles@npm:6.2.3" + checksum: f1b0829cf048cce870a305819f65ce2adcebc097b6d6479e12e955fd6225df9b9eb8b497083b764df796d94383ff20016cc4dbbae5b40f36138fb65a9d33c2e2 languageName: node linkType: hard @@ -6027,13 +5974,6 @@ __metadata: languageName: node linkType: hard -"arg@npm:^5.0.2": - version: 5.0.2 - resolution: "arg@npm:5.0.2" - checksum: 6c69ada1a9943d332d9e5382393e897c500908d91d5cb735a01120d5f71daf1b339b7b8980cbeaba8fd1afc68e658a739746179e4315a26e8a28951ff9930078 - languageName: node - linkType: hard - "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -6073,6 +6013,20 @@ __metadata: languageName: node linkType: hard +"async-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-function@npm:1.0.0" + checksum: 9102e246d1ed9b37ac36f57f0a6ca55226876553251a31fc80677e71471f463a54c872dc78d5d7f80740c8ba624395cccbe8b60f7b690c4418f487d8e9fd1106 + languageName: node + linkType: hard + +"async-generator-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-generator-function@npm:1.0.0" + checksum: 74a71a4a2dd7afd06ebb612f6d612c7f4766a351bedffde466023bf6dae629e46b0d2cd38786239e0fbf245de0c7df76035465e16d1213774a0efb22fec0d713 + languageName: node + linkType: hard + "autoprefixer@npm:10.4.21": version: 10.4.21 resolution: "autoprefixer@npm:10.4.21" @@ -6092,9 +6046,14 @@ __metadata: linkType: hard "b4a@npm:^1.6.4": - version: 1.6.7 - resolution: "b4a@npm:1.6.7" - checksum: afe4e239b49c0ef62236fe0d788ac9bd9d7eac7e9855b0d1835593cd0efcc7be394f9cc28a747a2ed2cdcb0a48c3528a551a196f472eb625457c711169c9efa2 + version: 1.7.3 + resolution: "b4a@npm:1.7.3" + peerDependencies: + react-native-b4a: "*" + peerDependenciesMeta: + react-native-b4a: + optional: true + checksum: b2e5f572bb2024b612eddedfbfce9626e103fd523da3d7bb8267f345bca6d7d4772ed00310527c7a629fc54184d5b1b47b73f8dd976d713aea7e16d2af38aecf languageName: node linkType: hard @@ -6111,15 +6070,15 @@ __metadata: linkType: hard "babel-plugin-polyfill-corejs2@npm:^0.4.14": - version: 0.4.14 - resolution: "babel-plugin-polyfill-corejs2@npm:0.4.14" + version: 0.4.15 + resolution: "babel-plugin-polyfill-corejs2@npm:0.4.15" dependencies: - "@babel/compat-data": ^7.27.7 - "@babel/helper-define-polyfill-provider": ^0.6.5 + "@babel/compat-data": ^7.28.6 + "@babel/helper-define-polyfill-provider": ^0.6.6 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: d654334c1b4390d08282416144b7b6f3d74d2cab44b2bfa2b6405c828882c82907b8b67698dce1be046c218d2d4fe5bf7fb6d01879938f3129dad969e8cfc44d + checksum: cf32e00ee54cdd75a3acec408f3467edc20cff4359c2bc5fb221144a489d6c0d5936031e18d66483613194a7012034b8a9e1237b84e9063f963f352efc1558bc languageName: node linkType: hard @@ -6136,64 +6095,50 @@ __metadata: linkType: hard "babel-plugin-polyfill-regenerator@npm:^0.6.5": - version: 0.6.5 - resolution: "babel-plugin-polyfill-regenerator@npm:0.6.5" + version: 0.6.6 + resolution: "babel-plugin-polyfill-regenerator@npm:0.6.6" dependencies: - "@babel/helper-define-polyfill-provider": ^0.6.5 + "@babel/helper-define-polyfill-provider": ^0.6.6 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: ed1932fa9a31e0752fd10ebf48ab9513a654987cab1182890839523cb898559d24ae0578fdc475d9f995390420e64eeaa4b0427045b56949dace3c725bc66dbb - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 - languageName: node - linkType: hard - -"balanced-match@npm:^3.0.0": - version: 3.0.1 - resolution: "balanced-match@npm:3.0.1" - checksum: 799bc086e80c5fe6c40e5bf486340d86ec76179017601a40dd0310ac92b44beaab19c55757a38bfd22e3b1572e5c3536e6f79050898f8fa9bbb7db4cfcf9e08e - languageName: node - linkType: hard - -"bare-events@npm:^2.2.0": - version: 2.5.0 - resolution: "bare-events@npm:2.5.0" - checksum: 5aa10716e7f33c5dfc471fd657eee2a33f2db0f78b3c83b5cdd1a45a7e7871114a69460ea96cd838807c55eb470b9e53dd0dfda8c83cced1352cc8253cebff48 + checksum: 8de7ea32856e75784601cacf8f4e3cbf04ce1fd05d56614b08b7bbe0674d1e59e37ccaa1c7ed16e3b181a63abe5bd43a1ab0e28b8c95618a9ebf0be5e24d6b25 languageName: node linkType: hard -"bare-events@npm:^2.5.4": - version: 2.6.0 - resolution: "bare-events@npm:2.6.0" - checksum: d6e95797ea539b39e2c31391d8410d3e0f959b19aa7cc3b7ba1f8acf188c7bd4cb5c596d6d4e6ad3836ffdf5285c8647d82667ca88fb9a1f4ab5de3f86fac3b9 +"bare-events@npm:^2.5.4, bare-events@npm:^2.7.0": + version: 2.8.2 + resolution: "bare-events@npm:2.8.2" + peerDependencies: + bare-abort-controller: "*" + peerDependenciesMeta: + bare-abort-controller: + optional: true + checksum: 97e6fc825bc984363a1f695c9a962b1b9f0ea467baa95d7059565a0aa31f4b5fc0f5eb71c087456ae3a436f39fce14a6147a12dd63aac0ff1d20cc5ad64cd780 languageName: node linkType: hard "bare-fs@npm:^4.0.1": - version: 4.1.6 - resolution: "bare-fs@npm:4.1.6" + version: 4.5.3 + resolution: "bare-fs@npm:4.5.3" dependencies: bare-events: ^2.5.4 bare-path: ^3.0.0 bare-stream: ^2.6.4 + bare-url: ^2.2.2 + fast-fifo: ^1.3.2 peerDependencies: bare-buffer: "*" peerDependenciesMeta: bare-buffer: optional: true - checksum: f623749f4fb5ddba2b7a9a2e58a5b8a1d4a3aa0f37ff26d271e14e01fd8bfc6e60dfa4a9ccb0e7f4abdceddce89d56f395498465270063af6d5313293e0edeea + checksum: add0e1655e95a06045db027cfd0b10cd7d468133c34727d4ec8ae5bcbe11abab59e0c494e979e890e37b13259617b62b24a96baf89a8d014197aa872c00c350f languageName: node linkType: hard "bare-os@npm:^3.0.1": - version: 3.6.1 - resolution: "bare-os@npm:3.6.1" - checksum: 2fcdbaa631e02e2b7a4a38ded4586ae8bef2d329c6933b9dca8c543b4af0ac3c257fdf0ff3339b83259e179e07873f300e61c75c0a1e6b796c0214b1fbae8696 + version: 3.6.2 + resolution: "bare-os@npm:3.6.2" + checksum: 339187a5f294b0433f2aa0e3180ffe635f82b9d4536fc818ec8b2b44af752421b1d4bb8eebefd5034cc462a26756900d67b95052ed5eeb2278cb2e23e566ae7a languageName: node linkType: hard @@ -6207,8 +6152,8 @@ __metadata: linkType: hard "bare-stream@npm:^2.6.4": - version: 2.6.5 - resolution: "bare-stream@npm:2.6.5" + version: 2.7.0 + resolution: "bare-stream@npm:2.7.0" dependencies: streamx: ^2.21.0 peerDependencies: @@ -6219,7 +6164,16 @@ __metadata: optional: true bare-events: optional: true - checksum: 6a3d4baf8ded0bdc465b7b0b65dfbb8e40f7520ee8899adcae5fd37949d5c520412164116659750ad841215b03ce761fe252a626cd4fe3ec9df0440c6fd07a96 + checksum: aa7a762b65271022ecc154c1f65eff37a9ff5aa1effd3f3065074b2885d4e6101c1f9fe06001cf3f88f73b56cc2a4b87ce70405d266891ac5082aeb1e1f6a310 + languageName: node + linkType: hard + +"bare-url@npm:^2.2.2": + version: 2.3.2 + resolution: "bare-url@npm:2.3.2" + dependencies: + bare-path: ^3.0.0 + checksum: 7b2a6335a55a010ffcc863f62cc5bfaa216b383bc05a8e7fb30caccb5600e09d403ad482fc671582eba531bbca4a891dba8eefa866f2e2d222b0a72f2460c340 languageName: node linkType: hard @@ -6231,18 +6185,18 @@ __metadata: linkType: hard "baseline-browser-mapping@npm:^2.9.0": - version: 2.9.14 - resolution: "baseline-browser-mapping@npm:2.9.14" + version: 2.9.19 + resolution: "baseline-browser-mapping@npm:2.9.19" bin: baseline-browser-mapping: dist/cli.js - checksum: c760c7cb5090b17c91aea2d7ad633d61491fea77f4eea1b2141b2b0d441ac887d3b433494c50e1490c2ba403e62e05606ad438a396c60bb41562c898a9fd7c6d + checksum: 5a9979a501f43d06188d6b4c1e5d540b3c5104d03439603af4bda0f1698b60ae2a44180fb7bdaeb9eea5118eb484a34e454211eb8cf0d104809fc668a0b2eb18 languageName: node linkType: hard "basic-ftp@npm:^5.0.2": - version: 5.0.5 - resolution: "basic-ftp@npm:5.0.5" - checksum: bc82d1c1c61cd838eaca96d68ece888bacf07546642fb6b9b8328ed410756f5935f8cf43a42cb44bb343e0565e28e908adc54c298bd2f1a6e0976871fb11fec6 + version: 5.1.0 + resolution: "basic-ftp@npm:5.1.0" + checksum: 883670e2bb7bc89e542f2f4aa649dab142b4ac852195dea3e08f892e4ac2d0772bde1f689fd8cf6e7113535bb0b61d9ed6351334f5e5b56a17cac64a9b58d351 languageName: node linkType: hard @@ -6299,26 +6253,6 @@ __metadata: languageName: node linkType: hard -"body-parser@npm:1.20.3": - version: 1.20.3 - resolution: "body-parser@npm:1.20.3" - dependencies: - bytes: 3.1.2 - content-type: ~1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.13.0 - raw-body: 2.5.2 - type-is: ~1.6.18 - unpipe: 1.0.0 - checksum: 1a35c59a6be8d852b00946330141c4f142c6af0f970faa87f10ad74f1ee7118078056706a05ae3093c54dabca9cd3770fa62a170a85801da1a4324f04381167d - languageName: node - linkType: hard - "body-parser@npm:^2.2.1": version: 2.2.2 resolution: "body-parser@npm:2.2.2" @@ -6336,6 +6270,26 @@ __metadata: languageName: node linkType: hard +"body-parser@npm:~1.20.3": + version: 1.20.4 + resolution: "body-parser@npm:1.20.4" + dependencies: + bytes: ~3.1.2 + content-type: ~1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: ~1.2.0 + http-errors: ~2.0.1 + iconv-lite: ~0.4.24 + on-finished: ~2.4.1 + qs: ~6.14.0 + raw-body: ~2.5.3 + type-is: ~1.6.18 + unpipe: ~1.0.0 + checksum: eaa212cff1737d2fbb49fc7aa1d71d9b456adea2dc3de388ff3c6d67b28028d6b1fa7e6cd77e3670b4cbd402ab011f80f6e5bb811480b53a28d11f33678c6298 + languageName: node + linkType: hard + "bonjour-service@npm:^1.2.1": version: 1.3.0 resolution: "bonjour-service@npm:1.3.0" @@ -6353,24 +6307,6 @@ __metadata: languageName: node linkType: hard -"brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" - dependencies: - balanced-match: ^1.0.0 - checksum: a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 - languageName: node - linkType: hard - -"brace-expansion@npm:^4.0.0": - version: 4.0.1 - resolution: "brace-expansion@npm:4.0.1" - dependencies: - balanced-match: ^3.0.0 - checksum: e75879c6f2defba2359b8d92ab9e0c9b884ecca2a65d686f252650d5e40f40209385aec4247acbe9fb2ed274330b25d55b71bb99a02386b2122573d40b3e64d1 - languageName: node - linkType: hard - "braces@npm:^3.0.3, braces@npm:~3.0.2": version: 3.0.3 resolution: "braces@npm:3.0.3" @@ -6380,21 +6316,7 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.21.5, browserslist@npm:^4.23.0, browserslist@npm:^4.24.0": - version: 4.24.3 - resolution: "browserslist@npm:4.24.3" - dependencies: - caniuse-lite: ^1.0.30001688 - electron-to-chromium: ^1.5.73 - node-releases: ^2.0.19 - update-browserslist-db: ^1.1.1 - bin: - browserslist: cli.js - checksum: 016efc9953350e3a7212edcfdd72210cb33b339c1a974a77c0715eb67d23d7e5cd0a073ce1c801ab09235d8c213425ca51b92d41bbb829b833872b45f885fe7c - languageName: node - linkType: hard - -"browserslist@npm:^4.24.4, browserslist@npm:^4.28.0": +"browserslist@npm:^4.21.5, browserslist@npm:^4.23.0, browserslist@npm:^4.24.0, browserslist@npm:^4.24.4, browserslist@npm:^4.28.1": version: 4.28.1 resolution: "browserslist@npm:4.28.1" dependencies: @@ -6446,43 +6368,42 @@ __metadata: languageName: node linkType: hard -"cacache@npm:^19.0.0, cacache@npm:^19.0.1": - version: 19.0.1 - resolution: "cacache@npm:19.0.1" +"cacache@npm:^20.0.0, cacache@npm:^20.0.1": + version: 20.0.3 + resolution: "cacache@npm:20.0.3" dependencies: - "@npmcli/fs": ^4.0.0 + "@npmcli/fs": ^5.0.0 fs-minipass: ^3.0.0 - glob: ^10.2.2 - lru-cache: ^10.0.1 + glob: ^13.0.0 + lru-cache: ^11.1.0 minipass: ^7.0.3 minipass-collect: ^2.0.1 minipass-flush: ^1.0.5 minipass-pipeline: ^1.2.4 p-map: ^7.0.2 - ssri: ^12.0.0 - tar: ^7.4.3 - unique-filename: ^4.0.0 - checksum: e95684717de6881b4cdaa949fa7574e3171946421cd8291769dd3d2417dbf7abf4aa557d1f968cca83dcbc95bed2a281072b09abfc977c942413146ef7ed4525 + ssri: ^13.0.0 + unique-filename: ^5.0.0 + checksum: 595e6b91d72972d596e1e9ccab8ddbf08b773f27240220b1b5b1b7b3f52173cfbcf095212e5d7acd86c3bd453c28e69b116469889c511615ef3589523d542639 languageName: node linkType: hard -"call-bind-apply-helpers@npm:^1.0.1": - version: 1.0.1 - resolution: "call-bind-apply-helpers@npm:1.0.1" +"call-bind-apply-helpers@npm:^1.0.1, call-bind-apply-helpers@npm:^1.0.2": + version: 1.0.2 + resolution: "call-bind-apply-helpers@npm:1.0.2" dependencies: es-errors: ^1.3.0 function-bind: ^1.1.2 - checksum: 3c55343261bb387c58a4762d15ad9d42053659a62681ec5eb50690c6b52a4a666302a01d557133ce6533e8bd04530ee3b209f23dd06c9577a1925556f8fcccdf + checksum: b2863d74fcf2a6948221f65d95b91b4b2d90cfe8927650b506141e669f7d5de65cea191bf788838bc40d13846b7886c5bc5c84ab96c3adbcf88ad69a72fcdc6b languageName: node linkType: hard "call-bound@npm:^1.0.2": - version: 1.0.3 - resolution: "call-bound@npm:1.0.3" + version: 1.0.4 + resolution: "call-bound@npm:1.0.4" dependencies: - call-bind-apply-helpers: ^1.0.1 - get-intrinsic: ^1.2.6 - checksum: a93bbe0f2d0a2d6c144a4349ccd0593d5d0d5d9309b69101710644af8964286420062f2cc3114dca120b9bc8cc07507952d4b1b3ea7672e0d7f6f1675efedb32 + call-bind-apply-helpers: ^1.0.2 + get-intrinsic: ^1.3.0 + checksum: 2f6399488d1c272f56306ca60ff696575e2b7f31daf23bc11574798c84d9f2759dceb0cb1f471a85b77f28962a7ac6411f51d283ea2e45319009a19b6ccab3b2 languageName: node linkType: hard @@ -6493,24 +6414,10 @@ __metadata: languageName: node linkType: hard -"camelcase-css@npm:^2.0.1": - version: 2.0.1 - resolution: "camelcase-css@npm:2.0.1" - checksum: 1cec2b3b3dcb5026688a470b00299a8db7d904c4802845c353dbd12d9d248d3346949a814d83bfd988d4d2e5b9904c07efe76fecd195a1d4f05b543e7c0b56b1 - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001688": - version: 1.0.30001689 - resolution: "caniuse-lite@npm:1.0.30001689" - checksum: 8d4152076517ac1dfd6d6733ecc8055f3cd3a8b679af8f5858e731312f03967f6a2184553636696e44cee39abdd9ccccc914716235791b0c25f68ef8dea4e24a - languageName: node - linkType: hard - "caniuse-lite@npm:^1.0.30001702, caniuse-lite@npm:^1.0.30001759": - version: 1.0.30001764 - resolution: "caniuse-lite@npm:1.0.30001764" - checksum: 10cfa46c5d11659d7c9c5151213b00b27876da66723f3c757e3f3294de1c477d3a89fff0efe03d0d787727fea2ca27910a0b68a5ac69483aedd474827eb52b96 + version: 1.0.30001767 + resolution: "caniuse-lite@npm:1.0.30001767" + checksum: c55acc7e05b0645b02988421649fab155fd6c1cfaa9b4289d8b597261d096209b7b7483891399143cc10eb46f86b6ec419396de049c05f7c9f8f1992c648be31 languageName: node linkType: hard @@ -6541,6 +6448,15 @@ __metadata: languageName: node linkType: hard +"chart.js@npm:^4.5.1": + version: 4.5.1 + resolution: "chart.js@npm:4.5.1" + dependencies: + "@kurkle/color": ^0.3.0 + checksum: 34b35b373642994b2adac197e91363625930530e29fc1baa6dbb411b5e1295f9f6572922003a0224a21a3019aec916567c1ed00c33b1373081f189fc188e5a7b + languageName: node + linkType: hard + "check-error@npm:^2.1.1": version: 2.1.3 resolution: "check-error@npm:2.1.3" @@ -6573,7 +6489,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^3.5.3, chokidar@npm:^3.6.0": +"chokidar@npm:^3.6.0": version: 3.6.0 resolution: "chokidar@npm:3.6.0" dependencies: @@ -6593,18 +6509,11 @@ __metadata: linkType: hard "chokidar@npm:^4.0.0": - version: 4.0.2 - resolution: "chokidar@npm:4.0.2" + version: 4.0.3 + resolution: "chokidar@npm:4.0.3" dependencies: readdirp: ^4.0.1 - checksum: ba7c43d249fa99bdc19c809b0085468e0709b2f1e27eb8573ed2b21af51667677d663dbc68d30ad9eb7620fc216131d98f9017952776db03063955ee58ed2834 - languageName: node - linkType: hard - -"chownr@npm:^2.0.0": - version: 2.0.0 - resolution: "chownr@npm:2.0.0" - checksum: c57cf9dd0791e2f18a5ee9c1a299ae6e801ff58fee96dc8bfd0dcb4738a6ce58dd252a3605b1c93c6418fe4f9d5093b28ffbf4d66648cb2a9c67eaef9679be2f + checksum: a8765e452bbafd04f3f2fad79f04222dd65f43161488bb6014a41099e6ca18d166af613d59a90771908c1c823efa3f46ba36b86ac50b701c20c1b9908c5fe36e languageName: node linkType: hard @@ -6622,15 +6531,15 @@ __metadata: languageName: node linkType: hard -"chromium-bidi@npm:10.5.1": - version: 10.5.1 - resolution: "chromium-bidi@npm:10.5.1" +"chromium-bidi@npm:13.0.1": + version: 13.0.1 + resolution: "chromium-bidi@npm:13.0.1" dependencies: mitt: ^3.0.1 zod: ^3.24.1 peerDependencies: devtools-protocol: "*" - checksum: 9c59b8025f65d7410c0eac65da3a52702f546404d31a485f404764870b8ed2a964175ebd28865d29efb60199cf2a514782aa68d8b943f71a17e602f0c3584f93 + checksum: 4e47640bd09b16440ce23a14f75887b8ee43cd272b8cac159760d42c49f44e2f2622488af63a7c304f130b81ec022e4cd15bb832411b2ea02fed9986258ed39b languageName: node linkType: hard @@ -6721,9 +6630,9 @@ __metadata: linkType: hard "color-name@npm:^2.0.0": - version: 2.0.0 - resolution: "color-name@npm:2.0.0" - checksum: 10a1addae41de2987d6b90dbd3cfade266c2e6f680ce21749911df4493b4fae07654862c6b5358bdd13e155461acb4eedaa5e0ba172bf13542cdcca10866cf2b + version: 2.1.0 + resolution: "color-name@npm:2.1.0" + checksum: eb014f71d87408e318e95d3f554f188370d354ba8e0ffa4341d0fd19de391bfe2bc96e563d4f6614644d676bc24f475560dffee3fe310c2d6865d007410a9a2b languageName: node linkType: hard @@ -6735,11 +6644,11 @@ __metadata: linkType: hard "color-string@npm:^2.0.1": - version: 2.0.1 - resolution: "color-string@npm:2.0.1" + version: 2.1.4 + resolution: "color-string@npm:2.1.4" dependencies: color-name: ^2.0.0 - checksum: a5ab024f78f67c0d5c1c995943ff95dce193beaa981492f6a36c05a9939a9db519e2d821d91df15677a47107fe90e4b12fd345729d755c65b543924db05c3a3f + checksum: f9caa29d529c549febeec813fcc0ecb184ff3dee92cec78f1fd3dfe2c4168fc1b74442efc40e34d2d677470967f570234d11086c3b137d6f9958a8fe12587fde languageName: node linkType: hard @@ -6764,13 +6673,6 @@ __metadata: languageName: node linkType: hard -"commander@npm:^4.0.0": - version: 4.1.1 - resolution: "commander@npm:4.1.1" - checksum: d7b9913ff92cae20cb577a4ac6fcc121bd6223319e54a40f51a14740a681ad5c574fd29a57da478a5f234a6fa6c52cbf0b7c641353e03c648b1ae85ba670b977 - languageName: node - linkType: hard - "commander@npm:^8.3.0": version: 8.3.0 resolution: "commander@npm:8.3.0" @@ -6788,17 +6690,17 @@ __metadata: linkType: hard "compression@npm:^1.7.4": - version: 1.7.5 - resolution: "compression@npm:1.7.5" + version: 1.8.1 + resolution: "compression@npm:1.8.1" dependencies: bytes: 3.1.2 compressible: ~2.0.18 debug: 2.6.9 negotiator: ~0.6.4 - on-headers: ~1.0.2 + on-headers: ~1.1.0 safe-buffer: 5.2.1 vary: ~1.1.2 - checksum: d624b5562492518eee82c4f1381ea36f69f1f10b4283bfc2dcafd7d4d7eeed17c3f0e8f2951798594b7064db7ac5a6198df34816bde2d56bb7c75ce1570880e9 + checksum: 906325935180cd3507d30ed898fb129deccab03689383d55536245a94610f5003923bb14c95ee6adc8d658ee13be549407eb4346ef55169045f3e41e9969808e languageName: node linkType: hard @@ -6809,13 +6711,6 @@ __metadata: languageName: node linkType: hard -"confbox@npm:^0.2.2": - version: 0.2.2 - resolution: "confbox@npm:0.2.2" - checksum: 335bc40d58f2785d2f8c5d45f0224e160dd634d42984ecf75b06addb6fe5f9584502ac9845d6f08f8ec066c8a796fd8b3c9ae9e8c7735047aa141d0e83469ab4 - languageName: node - linkType: hard - "connect-history-api-fallback@npm:^2.0.0": version: 2.0.0 resolution: "connect-history-api-fallback@npm:2.0.0" @@ -6823,7 +6718,14 @@ __metadata: languageName: node linkType: hard -"content-disposition@npm:0.5.4": +"content-disposition@npm:^1.0.0": + version: 1.0.1 + resolution: "content-disposition@npm:1.0.1" + checksum: f1ee5363968e7e4c491fcd9796d3c489ab29c4ea0bfa5dcc3379a9833d6044838367cf8a11c90b179cb2a8d471279ab259119c52e0d3e4ed30934ccd56b6d694 + languageName: node + linkType: hard + +"content-disposition@npm:~0.5.4": version: 0.5.4 resolution: "content-disposition@npm:0.5.4" dependencies: @@ -6832,13 +6734,6 @@ __metadata: languageName: node linkType: hard -"content-disposition@npm:^1.0.0": - version: 1.0.1 - resolution: "content-disposition@npm:1.0.1" - checksum: f1ee5363968e7e4c491fcd9796d3c489ab29c4ea0bfa5dcc3379a9833d6044838367cf8a11c90b179cb2a8d471279ab259119c52e0d3e4ed30934ccd56b6d694 - languageName: node - linkType: hard - "content-type@npm:^1.0.5, content-type@npm:~1.0.4, content-type@npm:~1.0.5": version: 1.0.5 resolution: "content-type@npm:1.0.5" @@ -6861,18 +6756,9 @@ __metadata: linkType: hard "convert@npm:^5.12.0": - version: 5.12.0 - resolution: "convert@npm:5.12.0" - dependencies: - wireit: 0.14.12 - checksum: 02cfe5345ac9183870bc87c9ba920c1ada77ad958ef092463f3f4b3a81bf833a709aedf79e22a26ee5baa810adda62ec6b93e3eed1c44f4e2392670bdc7dfb4c - languageName: node - linkType: hard - -"cookie-signature@npm:1.0.6": - version: 1.0.6 - resolution: "cookie-signature@npm:1.0.6" - checksum: f4e1b0a98a27a0e6e66fd7ea4e4e9d8e038f624058371bf4499cfcd8f3980be9a121486995202ba3fca74fbed93a407d6d54d43a43f96fd28d0bd7a06761591a + version: 5.14.1 + resolution: "convert@npm:5.14.1" + checksum: 375c2569717387351b94d3f392fb2c2a5f3a80a8e38d3e10bec778186aa1c8ebedaa4e1ae2935ab3e514b22041bfe7460943174d62d82014ad88da28477b0488 languageName: node linkType: hard @@ -6883,14 +6769,14 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.7.1": - version: 0.7.1 - resolution: "cookie@npm:0.7.1" - checksum: cec5e425549b3650eb5c3498a9ba3cde0b9cd419e3b36e4b92739d30b4d89e0b678b98c1ddc209ce7cf958cd3215671fd6ac47aec21f10c2a0cc68abd399d8a7 +"cookie-signature@npm:~1.0.6": + version: 1.0.7 + resolution: "cookie-signature@npm:1.0.7" + checksum: 1a62808cd30d15fb43b70e19829b64d04b0802d8ef00275b57d152de4ae6a3208ca05c197b6668d104c4d9de389e53ccc2d3bc6bcaaffd9602461417d8c40710 languageName: node linkType: hard -"cookie@npm:^0.7.1": +"cookie@npm:^0.7.1, cookie@npm:~0.7.1": version: 0.7.2 resolution: "cookie@npm:0.7.2" checksum: 9bf8555e33530affd571ea37b615ccad9b9a34febbf2c950c86787088eb00a8973690833b0f8ebd6b69b753c62669ea60cec89178c1fb007bf0749abed74f93e @@ -6922,11 +6808,11 @@ __metadata: linkType: hard "core-js-compat@npm:^3.43.0": - version: 3.47.0 - resolution: "core-js-compat@npm:3.47.0" + version: 3.48.0 + resolution: "core-js-compat@npm:3.48.0" dependencies: - browserslist: ^4.28.0 - checksum: 425c8cb4c3277a11f3d7d4752c53e5903892635126ed1cdc326a1cd7d961606c5d2c951493f1c783e624f9cdc1ec791c6db68dc19988d68f112d7d82a4c39c9a + browserslist: ^4.28.1 + checksum: 2625622bc7c4a43a134f7d01eff48bde93100a4b5c11b6a3972bc22bcd403c6d060f26f4786ca21376fb159771f008738a5b6f283ad67b19f94e342fa8d28288 languageName: node linkType: hard @@ -6938,12 +6824,12 @@ __metadata: linkType: hard "cors@npm:^2.8.5": - version: 2.8.5 - resolution: "cors@npm:2.8.5" + version: 2.8.6 + resolution: "cors@npm:2.8.6" dependencies: object-assign: ^4 vary: ^1 - checksum: ced838404ccd184f61ab4fdc5847035b681c90db7ac17e428f3d81d69e2989d2b680cc254da0e2554f5ed4f8a341820a1ce3d1c16b499f6e2f47a1b9b07b5006 + checksum: a967922b00fd17d836d21308c66ab9081d6c0f7dc019486ba1643a58281b12fc27d8c260471ddca72874b5bfe17a2d471ff8762d34f6009022ff749ec1136220 languageName: node linkType: hard @@ -6989,7 +6875,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.5": +"cross-spawn@npm:^7.0.5": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -7242,9 +7128,9 @@ __metadata: linkType: hard "d3-format@npm:1 - 3, d3-format@npm:3": - version: 3.1.0 - resolution: "d3-format@npm:3.1.0" - checksum: f345ec3b8ad3cab19bff5dead395bd9f5590628eb97a389b1dd89f0b204c7c4fc1d9520f13231c2c7cf14b7c9a8cf10f8ef15bde2befbab41454a569bd706ca2 + version: 3.1.2 + resolution: "d3-format@npm:3.1.2" + checksum: 2ce13417b3186311df3fd924028cd516ec3e96d7c3eb6df9c83f6c2ed43de1717e6c5119a385b7744ef84e2b8a4c678ad95a2b2998391803ceb0d809e235cff4 languageName: node linkType: hard @@ -7475,12 +7361,12 @@ __metadata: linkType: hard "data-urls@npm:^6.0.0": - version: 6.0.0 - resolution: "data-urls@npm:6.0.0" + version: 6.0.1 + resolution: "data-urls@npm:6.0.1" dependencies: - whatwg-mimetype: ^4.0.0 - whatwg-url: ^15.0.0 - checksum: a47f0dde184337c4f168d455aedf0b486fed87b6ca583b4b9ad55d1515f4836b418d4bdc5b5b6fc55e321feb826029586a0d47e1c9a9e7ac4d52a78faceb7fb0 + whatwg-mimetype: ^5.0.0 + whatwg-url: ^15.1.0 + checksum: 6ab8025df0ee497bfb12241f815fd3f3438dd34cd851c0801c16aa4e1e70f4f68d6334e3176ca340fe4084622b8a299a98b3d3059bbca671f1eaf8bae1088ec2 languageName: node linkType: hard @@ -7507,19 +7393,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.4, debug@npm:^4.3.6": - version: 4.4.0 - resolution: "debug@npm:4.4.0" - dependencies: - ms: ^2.1.3 - peerDependenciesMeta: - supports-color: - optional: true - checksum: fb42df878dd0e22816fc56e1fdca9da73caa85212fbe40c868b1295a6878f9101ae684f4eeef516c13acfc700f5ea07f1136954f43d4cd2d477a811144136479 - languageName: node - linkType: hard - -"debug@npm:^4.4.0, debug@npm:^4.4.1, debug@npm:^4.4.3": +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.4, debug@npm:^4.3.6, debug@npm:^4.4.0, debug@npm:^4.4.1, debug@npm:^4.4.3": version: 4.4.3 resolution: "debug@npm:4.4.3" dependencies: @@ -7553,19 +7427,19 @@ __metadata: linkType: hard "default-browser-id@npm:^5.0.0": - version: 5.0.0 - resolution: "default-browser-id@npm:5.0.0" - checksum: 185bfaecec2c75fa423544af722a3469b20704c8d1942794a86e4364fe7d9e8e9f63241a5b769d61c8151993bc65833a5b959026fa1ccea343b3db0a33aa6deb + version: 5.0.1 + resolution: "default-browser-id@npm:5.0.1" + checksum: 52c637637bcd76bfe974462a2f1dd75cb04784c2852935575760f82e1fd338e5e80d3c45a9b01fdbb1e450553a830bb163b004d2eca223c5573989f82232a072 languageName: node linkType: hard "default-browser@npm:^5.2.1": - version: 5.2.1 - resolution: "default-browser@npm:5.2.1" + version: 5.4.0 + resolution: "default-browser@npm:5.4.0" dependencies: bundle-name: ^4.1.0 default-browser-id: ^5.0.0 - checksum: afab7eff7b7f5f7a94d9114d1ec67273d3fbc539edf8c0f80019879d53aa71e867303c6f6d7cffeb10a6f3cfb59d4f963dba3f9c96830b4540cc7339a1bf9840 + checksum: cac0222ca5c9a3387d25337228689652ab33679a6566995c7194a75af7e554e91ec9ac92a70bfaa8e8089eae9f466ae99267bb38601282aade89b200f50a765c languageName: node linkType: hard @@ -7624,26 +7498,17 @@ __metadata: languageName: node linkType: hard -"destroy@npm:1.2.0": +"destroy@npm:1.2.0, destroy@npm:~1.2.0": version: 1.2.0 resolution: "destroy@npm:1.2.0" checksum: 0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38 languageName: node linkType: hard -"detect-libc@npm:^1.0.3": - version: 1.0.3 - resolution: "detect-libc@npm:1.0.3" - bin: - detect-libc: ./bin/detect-libc.js - checksum: daaaed925ffa7889bd91d56e9624e6c8033911bb60f3a50a74a87500680652969dbaab9526d1e200a4c94acf80fc862a22131841145a0a8482d60a99c24f4a3e - languageName: node - linkType: hard - -"detect-libc@npm:^2.0.1": - version: 2.0.3 - resolution: "detect-libc@npm:2.0.3" - checksum: 2ba6a939ae55f189aea996ac67afceb650413c7a34726ee92c40fb0deb2400d57ef94631a8a3f052055eea7efb0f99a9b5e6ce923415daa3e68221f963cfc27d +"detect-libc@npm:^2.0.1, detect-libc@npm:^2.0.3": + version: 2.1.2 + resolution: "detect-libc@npm:2.1.2" + checksum: 471740d52365084c4b2ae359e507b863f2b1d79b08a92835ebdf701918e08fc9cfba175b3db28483ca33b155e1311a91d69dc42c6d192b476f41a9e1f094ce6a languageName: node linkType: hard @@ -7654,31 +7519,17 @@ __metadata: languageName: node linkType: hard -"devtools-protocol@npm:0.0.1521046": - version: 0.0.1521046 - resolution: "devtools-protocol@npm:0.0.1521046" - checksum: 3bf6782d0cdd2a9c025cd476231d7384dc2a9885d24ae8333f951646725acb091cf18c487109db5985d3934e3ea0d7439f189e27a95fc415c790b1478771409c - languageName: node - linkType: hard - -"didyoumean@npm:^1.2.2": - version: 1.2.2 - resolution: "didyoumean@npm:1.2.2" - checksum: d5d98719d58b3c2fa59663c4c42ba9716f1fd01245c31d5fce31915bd3aa26e6aac149788e007358f778ebbd68a2256eb5973e8ca6f221df221ba060115acf2e +"devtools-protocol@npm:0.0.1551306": + version: 0.0.1551306 + resolution: "devtools-protocol@npm:0.0.1551306" + checksum: 0116685433e21f3fb10acd68ee3337aed1586c95784e61d506d8d5b9133150ce4ce25a92f3e2b0d7635e2c8e9eed053e436b5703750f1952542d15ac432d15c2 languageName: node linkType: hard "diff@npm:^4.0.1": - version: 4.0.2 - resolution: "diff@npm:4.0.2" - checksum: f2c09b0ce4e6b301c221addd83bf3f454c0bc00caa3dd837cf6c127d6edf7223aa2bbe3b688feea110b7f262adbfc845b757c44c8a9f8c0c5b15d8fa9ce9d20d - languageName: node - linkType: hard - -"dlv@npm:^1.1.3": - version: 1.1.3 - resolution: "dlv@npm:1.1.3" - checksum: d7381bca22ed11933a1ccf376db7a94bee2c57aa61e490f680124fa2d1cd27e94eba641d9f45be57caab4f9a6579de0983466f620a2cd6230d7ec93312105ae7 + version: 4.0.4 + resolution: "diff@npm:4.0.4" + checksum: e3f1c368778b16f9e7e4fd4199d04913bba9b017c37fbca7642b3613ebefcf3b18a4bd55e5f7074dc023fc95c96bd265f72114044e62cebae7f9a0f53bc36ace languageName: node linkType: hard @@ -7738,18 +7589,18 @@ __metadata: linkType: hard "dompurify@npm:^3.2.5": - version: 3.3.0 - resolution: "dompurify@npm:3.3.0" + version: 3.3.1 + resolution: "dompurify@npm:3.3.1" dependencies: "@types/trusted-types": ^2.0.7 dependenciesMeta: "@types/trusted-types": optional: true - checksum: 425c181ac531cb15f93be85dc6efb1eb535d7c53ad0752b305043fe43e76c5ef144c2aa3670da2a52bec253c0aa302c06545cd04012396dc81d52cf86529097b + checksum: 884fe0acc21a9a2e5aa1b8ce4cecc8f9a71217423b389f760fca7b44595d3c9376d234f1c4ba16d79824789762b3d611d10653c4a90a7e23b351b71e5ef7dd33 languageName: node linkType: hard -"domutils@npm:^3.2.1, domutils@npm:^3.2.2": +"domutils@npm:^3.2.2": version: 3.2.2 resolution: "domutils@npm:3.2.2" dependencies: @@ -7760,7 +7611,7 @@ __metadata: languageName: node linkType: hard -"dunder-proto@npm:^1.0.0": +"dunder-proto@npm:^1.0.1": version: 1.0.1 resolution: "dunder-proto@npm:1.0.1" dependencies: @@ -7771,13 +7622,6 @@ __metadata: languageName: node linkType: hard -"eastasianwidth@npm:^0.2.0": - version: 0.2.0 - resolution: "eastasianwidth@npm:0.2.0" - checksum: 7d00d7cd8e49b9afa762a813faac332dee781932d6f2c848dc348939c4253f1d4564341b7af1d041853bc3f32c2ef141b58e0a4d9862c17a7f08f68df1e0f1ed - languageName: node - linkType: hard - "ee-first@npm:1.1.1": version: 1.1.1 resolution: "ee-first@npm:1.1.1" @@ -7786,23 +7630,16 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.5.263": - version: 1.5.267 - resolution: "electron-to-chromium@npm:1.5.267" - checksum: 923a21ea4c3f2536eb7ccf80e92d9368a2e5a13e6deccb1d94c31b5a5b4e10e722149b85db9892e9819150f1c43462692a92dc85ba0c205a4eb578e173b3ab36 - languageName: node - linkType: hard - -"electron-to-chromium@npm:^1.5.73": - version: 1.5.74 - resolution: "electron-to-chromium@npm:1.5.74" - checksum: e93db5fdfafe927dcefe2ffef5b8670ae0c340eb8a4fe176918ec8efa53c37aff0ba4c3649c234950af2809d16a186ffead64dd921c9021d629658bf6d17c21f + version: 1.5.283 + resolution: "electron-to-chromium@npm:1.5.283" + checksum: 50929e6289390da362ad72f7af094a28a4c0589770f22dc466de9eae33105bb0b809167b42a2ce2d0993e69b64c8d8764bb3dc7f8aaa2c89cec9906800c10aa9 languageName: node linkType: hard "emoji-regex@npm:^10.3.0": - version: 10.4.0 - resolution: "emoji-regex@npm:10.4.0" - checksum: a6d9a0e454829a52e664e049847776ee1fff5646617b06cd87de7c03ce1dfcce4102a3b154d5e9c8e90f8125bc120fc1fe114d523dddf60a8a161f26c72658d2 + version: 10.6.0 + resolution: "emoji-regex@npm:10.6.0" + checksum: 8785f6a7ec4559c931bd6640f748fe23791f5af4c743b131d458c5551b4aa7da2a9cd882518723cb3859e8b0b59b0cc08f2ce0f8e65c61a026eed71c2dc407d5 languageName: node linkType: hard @@ -7813,13 +7650,6 @@ __metadata: languageName: node linkType: hard -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 8487182da74aabd810ac6d6f1994111dfc0e331b01271ae01ec1eb0ad7b5ecc2bbbbd2f053c05cb55a1ac30449527d819bbfbf0e3de1023db308cbcb47f86601 - languageName: node - linkType: hard - "emoji-toolkit@npm:>= 8.0.0 < 10.0.0": version: 9.0.1 resolution: "emoji-toolkit@npm:9.0.1" @@ -7841,13 +7671,6 @@ __metadata: languageName: node linkType: hard -"encodeurl@npm:~1.0.2": - version: 1.0.2 - resolution: "encodeurl@npm:1.0.2" - checksum: e50e3d508cdd9c4565ba72d2012e65038e5d71bdc9198cb125beb6237b5b1ade6c0d343998da9e170fb2eae52c1bed37d4d6d98a46ea423a0cddbed5ac3f780c - languageName: node - linkType: hard - "encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" @@ -7858,15 +7681,15 @@ __metadata: linkType: hard "end-of-stream@npm:^1.1.0": - version: 1.4.4 - resolution: "end-of-stream@npm:1.4.4" + version: 1.4.5 + resolution: "end-of-stream@npm:1.4.5" dependencies: once: ^1.4.0 - checksum: 530a5a5a1e517e962854a31693dbb5c0b2fc40b46dad2a56a2deec656ca040631124f4795823acc68238147805f8b021abbe221f4afed5ef3c8e8efc2024908b + checksum: 1e0cfa6e7f49887544e03314f9dfc56a8cb6dde910cbb445983ecc2ff426fc05946df9d75d8a21a3a64f2cecfe1bf88f773952029f46756b2ed64a24e95b1fb8 languageName: node linkType: hard -"enhanced-resolve@npm:^5.17.3": +"enhanced-resolve@npm:^5.17.4": version: 5.18.4 resolution: "enhanced-resolve@npm:5.18.4" dependencies: @@ -7890,6 +7713,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:^7.0.1": + version: 7.0.1 + resolution: "entities@npm:7.0.1" + checksum: 5ee49e52e64eafc63251585f74eae50f259ea2169dbbf5380843dcd97c79bfe430a58e7f34012ab67a8e258f6ef9f92d721d149ffc88c89039e155f1bcf48a53 + languageName: node + linkType: hard + "env-paths@npm:^2.2.0, env-paths@npm:^2.2.1": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -7923,11 +7753,11 @@ __metadata: linkType: hard "error-ex@npm:^1.3.1": - version: 1.3.2 - resolution: "error-ex@npm:1.3.2" + version: 1.3.4 + resolution: "error-ex@npm:1.3.4" dependencies: is-arrayish: ^0.2.1 - checksum: c1c2b8b65f9c91b0f9d75f0debaa7ec5b35c266c2cac5de412c1a6de86d4cbae04ae44e510378cb14d032d0645a36925d0186f8bb7367bcc629db256b743a001 + checksum: 25136c0984569c8d68417036a9a1624804314296f24675199a391e5d20b2e26fe6d9304d40901293fa86900603a229983c9a8921ea7f1d16f814c2db946ff4ef languageName: node linkType: hard @@ -7940,15 +7770,8 @@ __metadata: "es-errors@npm:^1.3.0": version: 1.3.0 - resolution: "es-errors@npm:1.3.0" - checksum: ec1414527a0ccacd7f15f4a3bc66e215f04f595ba23ca75cdae0927af099b5ec865f9f4d33e9d7e86f512f252876ac77d4281a7871531a50678132429b1271b5 - languageName: node - linkType: hard - -"es-module-lexer@npm:^1.2.1": - version: 1.5.4 - resolution: "es-module-lexer@npm:1.5.4" - checksum: a0cf04fb92d052647ac7d818d1913b98d3d3d0f5b9d88f0eafb993436e4c3e2c958599db68839d57f2dfa281fdf0f60e18d448eb78fc292c33c0f25635b6854f + resolution: "es-errors@npm:1.3.0" + checksum: ec1414527a0ccacd7f15f4a3bc66e215f04f595ba23ca75cdae0927af099b5ec865f9f4d33e9d7e86f512f252876ac77d4281a7871531a50678132429b1271b5 languageName: node linkType: hard @@ -7959,12 +7782,19 @@ __metadata: languageName: node linkType: hard -"es-object-atoms@npm:^1.0.0": - version: 1.0.0 - resolution: "es-object-atoms@npm:1.0.0" +"es-module-lexer@npm:^2.0.0": + version: 2.0.0 + resolution: "es-module-lexer@npm:2.0.0" + checksum: 6290c43cc9bf6c9f9167b4be8c0105137401fbbd9d503d89880f7e811286cd33ab628407e7dea3c14d41cf9e634e580e5d9952907003a88c7fb2461de6f1b2c1 + languageName: node + linkType: hard + +"es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": + version: 1.1.1 + resolution: "es-object-atoms@npm:1.1.1" dependencies: es-errors: ^1.3.0 - checksum: 26f0ff78ab93b63394e8403c353842b2272836968de4eafe97656adfb8a7c84b9099bf0fe96ed58f4a4cddc860f6e34c77f91649a58a5daa4a9c40b902744e3c + checksum: 214d3767287b12f36d3d7267ef342bbbe1e89f899cfd67040309fc65032372a8e60201410a99a1645f2f90c1912c8c49c8668066f6bdd954bcd614dda2e3da97 languageName: node linkType: hard @@ -8067,35 +7897,35 @@ __metadata: linkType: hard "esbuild@npm:^0.25.0": - version: 0.25.8 - resolution: "esbuild@npm:0.25.8" - dependencies: - "@esbuild/aix-ppc64": 0.25.8 - "@esbuild/android-arm": 0.25.8 - "@esbuild/android-arm64": 0.25.8 - "@esbuild/android-x64": 0.25.8 - "@esbuild/darwin-arm64": 0.25.8 - "@esbuild/darwin-x64": 0.25.8 - "@esbuild/freebsd-arm64": 0.25.8 - "@esbuild/freebsd-x64": 0.25.8 - "@esbuild/linux-arm": 0.25.8 - "@esbuild/linux-arm64": 0.25.8 - "@esbuild/linux-ia32": 0.25.8 - "@esbuild/linux-loong64": 0.25.8 - "@esbuild/linux-mips64el": 0.25.8 - "@esbuild/linux-ppc64": 0.25.8 - "@esbuild/linux-riscv64": 0.25.8 - "@esbuild/linux-s390x": 0.25.8 - "@esbuild/linux-x64": 0.25.8 - "@esbuild/netbsd-arm64": 0.25.8 - "@esbuild/netbsd-x64": 0.25.8 - "@esbuild/openbsd-arm64": 0.25.8 - "@esbuild/openbsd-x64": 0.25.8 - "@esbuild/openharmony-arm64": 0.25.8 - "@esbuild/sunos-x64": 0.25.8 - "@esbuild/win32-arm64": 0.25.8 - "@esbuild/win32-ia32": 0.25.8 - "@esbuild/win32-x64": 0.25.8 + version: 0.25.12 + resolution: "esbuild@npm:0.25.12" + dependencies: + "@esbuild/aix-ppc64": 0.25.12 + "@esbuild/android-arm": 0.25.12 + "@esbuild/android-arm64": 0.25.12 + "@esbuild/android-x64": 0.25.12 + "@esbuild/darwin-arm64": 0.25.12 + "@esbuild/darwin-x64": 0.25.12 + "@esbuild/freebsd-arm64": 0.25.12 + "@esbuild/freebsd-x64": 0.25.12 + "@esbuild/linux-arm": 0.25.12 + "@esbuild/linux-arm64": 0.25.12 + "@esbuild/linux-ia32": 0.25.12 + "@esbuild/linux-loong64": 0.25.12 + "@esbuild/linux-mips64el": 0.25.12 + "@esbuild/linux-ppc64": 0.25.12 + "@esbuild/linux-riscv64": 0.25.12 + "@esbuild/linux-s390x": 0.25.12 + "@esbuild/linux-x64": 0.25.12 + "@esbuild/netbsd-arm64": 0.25.12 + "@esbuild/netbsd-x64": 0.25.12 + "@esbuild/openbsd-arm64": 0.25.12 + "@esbuild/openbsd-x64": 0.25.12 + "@esbuild/openharmony-arm64": 0.25.12 + "@esbuild/sunos-x64": 0.25.12 + "@esbuild/win32-arm64": 0.25.12 + "@esbuild/win32-ia32": 0.25.12 + "@esbuild/win32-x64": 0.25.12 dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -8151,7 +7981,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 018e7b151c86df559f30e9b4da95cd5f6c76715818ee1c584ea3a4d19400be75f705f6d57486af2884ad7c1654b791e28419d34c0755186b194d3411745d074c + checksum: 3d1dc181338e2c44f4374508e9d0da3e7ae90f65d7f3f5d8076ff401a1726c5c9ecc86cfc825249349f1652e12d5ae13f02bcaa4d9487c88c7a11167f52ba353 languageName: node linkType: hard @@ -8350,9 +8180,18 @@ __metadata: linkType: hard "eventemitter3@npm:^5.0.1": - version: 5.0.1 - resolution: "eventemitter3@npm:5.0.1" - checksum: 543d6c858ab699303c3c32e0f0f47fc64d360bf73c3daf0ac0b5079710e340d6fe9f15487f94e66c629f5f82cd1a8678d692f3dbb6f6fcd1190e1b97fcad36f8 + version: 5.0.4 + resolution: "eventemitter3@npm:5.0.4" + checksum: bcbd2c3a9d2553c2289623ede8aab474d5c92bcbf18e5fe76f0e550c2b7801afb5a4351c7f11e8ee2379cca1ee48316aeb98fc3b946b7dd1f47a4c1ee8c4dcf2 + languageName: node + linkType: hard + +"events-universal@npm:^1.0.0": + version: 1.0.1 + resolution: "events-universal@npm:1.0.1" + dependencies: + bare-events: ^2.7.0 + checksum: fb8451c98535bde30585004303a368d55c38e5bc3ed6aa9b5d29fecaabaf8ec276a33ff77dcc1d1c05eecf83b8161f184cabc9a03b76a06c10e9a4ce827a6abc languageName: node linkType: hard @@ -8387,9 +8226,9 @@ __metadata: linkType: hard "exponential-backoff@npm:^3.1.1": - version: 3.1.1 - resolution: "exponential-backoff@npm:3.1.1" - checksum: 3d21519a4f8207c99f7457287291316306255a328770d320b401114ec8481986e4e467e854cb9914dd965e0a1ca810a23ccb559c642c88f4c7f55c55778a9b48 + version: 3.1.3 + resolution: "exponential-backoff@npm:3.1.3" + checksum: 471fdb70fd3d2c08a74a026973bdd4105b7832911f610ca67bbb74e39279411c1eed2f2a110c9d41c2edd89459ba58fdaba1c174beed73e7a42d773882dcff82 languageName: node linkType: hard @@ -8403,41 +8242,41 @@ __metadata: linkType: hard "express@npm:^4.21.2": - version: 4.21.2 - resolution: "express@npm:4.21.2" + version: 4.22.1 + resolution: "express@npm:4.22.1" dependencies: accepts: ~1.3.8 array-flatten: 1.1.1 - body-parser: 1.20.3 - content-disposition: 0.5.4 + body-parser: ~1.20.3 + content-disposition: ~0.5.4 content-type: ~1.0.4 - cookie: 0.7.1 - cookie-signature: 1.0.6 + cookie: ~0.7.1 + cookie-signature: ~1.0.6 debug: 2.6.9 depd: 2.0.0 encodeurl: ~2.0.0 escape-html: ~1.0.3 etag: ~1.8.1 - finalhandler: 1.3.1 - fresh: 0.5.2 - http-errors: 2.0.0 + finalhandler: ~1.3.1 + fresh: ~0.5.2 + http-errors: ~2.0.0 merge-descriptors: 1.0.3 methods: ~1.1.2 - on-finished: 2.4.1 + on-finished: ~2.4.1 parseurl: ~1.3.3 - path-to-regexp: 0.1.12 + path-to-regexp: ~0.1.12 proxy-addr: ~2.0.7 - qs: 6.13.0 + qs: ~6.14.0 range-parser: ~1.2.1 safe-buffer: 5.2.1 - send: 0.19.0 - serve-static: 1.16.2 + send: ~0.19.0 + serve-static: ~1.16.2 setprototypeof: 1.2.0 - statuses: 2.0.1 + statuses: ~2.0.1 type-is: ~1.6.18 utils-merge: 1.0.1 vary: ~1.1.2 - checksum: 3aef1d355622732e20b8f3a7c112d4391d44e2131f4f449e1f273a309752a41abfad714e881f177645517cbe29b3ccdc10b35e7e25c13506114244a5b72f549d + checksum: 38fd76585f6a2394e02d499f852fc70c94c9b1527bd5812eb5ee45c23b7f1297baaf13c55162253b14c1e36939b8401429d6594095e63d01ca77447dac72894e languageName: node linkType: hard @@ -8477,13 +8316,6 @@ __metadata: languageName: node linkType: hard -"exsolve@npm:^1.0.7": - version: 1.0.7 - resolution: "exsolve@npm:1.0.7" - checksum: 3adce048e4b1b08580aaabf38c7f92f78e1a662a1776fc02d7e9500d5ce4a30cd3f8e62206768821aa2c3bc2411a699146ebc5710ccc3d46e91199dbfff89f54 - languageName: node - linkType: hard - "extract-zip@npm:^2.0.1": version: 2.0.1 resolution: "extract-zip@npm:2.0.1" @@ -8515,7 +8347,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:3.3.3, fast-glob@npm:^3.2.11, fast-glob@npm:^3.3.3": +"fast-glob@npm:3.3.3, fast-glob@npm:^3.3.3": version: 3.3.3 resolution: "fast-glob@npm:3.3.3" dependencies: @@ -8528,23 +8360,10 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.3.2": - version: 3.3.2 - resolution: "fast-glob@npm:3.3.2" - dependencies: - "@nodelib/fs.stat": ^2.0.2 - "@nodelib/fs.walk": ^1.2.3 - glob-parent: ^5.1.2 - merge2: ^1.3.0 - micromatch: ^4.0.4 - checksum: 900e4979f4dbc3313840078419245621259f349950411ca2fa445a2f9a1a6d98c3b5e7e0660c5ccd563aa61abe133a21765c6c0dec8e57da1ba71d8000b05ec1 - languageName: node - linkType: hard - "fast-uri@npm:^3.0.1": - version: 3.0.3 - resolution: "fast-uri@npm:3.0.3" - checksum: c52e6c86465f5c240e84a4485fb001088cc743d261a4b54b0050ce4758b1648bdbe53da1328ef9620149dca1435e3de64184f226d7c0a3656cb5837b3491e149 + version: 3.1.0 + resolution: "fast-uri@npm:3.1.0" + checksum: daab0efd3548cc53d0db38ecc764d125773f8bd70c34552ff21abdc6530f26fa4cb1771f944222ca5e61a0a1a85d01a104848ff88c61736de445d97bd616ea7e languageName: node linkType: hard @@ -8556,11 +8375,11 @@ __metadata: linkType: hard "fastq@npm:^1.6.0": - version: 1.17.1 - resolution: "fastq@npm:1.17.1" + version: 1.20.1 + resolution: "fastq@npm:1.20.1" dependencies: reusify: ^1.0.4 - checksum: a8c5b26788d5a1763f88bae56a8ddeee579f935a831c5fe7a8268cea5b0a91fbfe705f612209e02d639b881d7b48e461a50da4a10cfaa40da5ca7cc9da098d88 + checksum: 49128edbf05e682bee3c1db3d2dfc7da195469065ef014d8368c555d829932313ae2ddf584bb03146409b0d5d9fdb387c471075483a7319b52f777ad91128ed8 languageName: node linkType: hard @@ -8626,21 +8445,6 @@ __metadata: languageName: node linkType: hard -"finalhandler@npm:1.3.1": - version: 1.3.1 - resolution: "finalhandler@npm:1.3.1" - dependencies: - debug: 2.6.9 - encodeurl: ~2.0.0 - escape-html: ~1.0.3 - on-finished: 2.4.1 - parseurl: ~1.3.3 - statuses: 2.0.1 - unpipe: ~1.0.0 - checksum: a8c58cd97c9cd47679a870f6833a7b417043f5a288cd6af6d0f49b476c874a506100303a128b6d3b654c3d74fa4ff2ffed68a48a27e8630cda5c918f2977dcf4 - languageName: node - linkType: hard - "finalhandler@npm:^2.1.0": version: 2.1.1 resolution: "finalhandler@npm:2.1.1" @@ -8655,6 +8459,21 @@ __metadata: languageName: node linkType: hard +"finalhandler@npm:~1.3.1": + version: 1.3.2 + resolution: "finalhandler@npm:1.3.2" + dependencies: + debug: 2.6.9 + encodeurl: ~2.0.0 + escape-html: ~1.0.3 + on-finished: ~2.4.1 + parseurl: ~1.3.3 + statuses: ~2.0.2 + unpipe: ~1.0.0 + checksum: 4bce6b3e1f6998497a8ef8418bc307ef09daee05acc5a69a36da665565cbeb86218de1932e42dbf2eebf18f580053d2061eddbdeff9e312de45d46fbf4dd36ec + languageName: node + linkType: hard + "find-up@npm:^5.0.0": version: 5.0.0 resolution: "find-up@npm:5.0.0" @@ -8675,22 +8494,12 @@ __metadata: linkType: hard "follow-redirects@npm:^1.0.0": - version: 1.15.9 - resolution: "follow-redirects@npm:1.15.9" + version: 1.15.11 + resolution: "follow-redirects@npm:1.15.11" peerDependenciesMeta: debug: optional: true - checksum: 859e2bacc7a54506f2bf9aacb10d165df78c8c1b0ceb8023f966621b233717dab56e8d08baadc3ad3b9db58af290413d585c999694b7c146aaf2616340c3d2a6 - languageName: node - linkType: hard - -"foreground-child@npm:^3.1.0": - version: 3.3.0 - resolution: "foreground-child@npm:3.3.0" - dependencies: - cross-spawn: ^7.0.0 - signal-exit: ^4.0.1 - checksum: 1989698488f725b05b26bc9afc8a08f08ec41807cd7b92ad85d96004ddf8243fd3e79486b8348c64a3011ae5cc2c9f0936af989e1f28339805d8bc178a75b451 + checksum: 20bf55e9504f59e6cc3743ba27edb2ebf41edea1baab34799408f2c050f73f0c612728db21c691276296d2795ea8a812dc532a98e8793619fcab91abe06d017f languageName: node linkType: hard @@ -8719,13 +8528,6 @@ __metadata: languageName: node linkType: hard -"fresh@npm:0.5.2": - version: 0.5.2 - resolution: "fresh@npm:0.5.2" - checksum: 13ea8b08f91e669a64e3ba3a20eb79d7ca5379a81f1ff7f4310d54e2320645503cc0c78daedc93dfb6191287295f6479544a649c64d8e41a1c0fb0c221552346 - languageName: node - linkType: hard - "fresh@npm:^2.0.0": version: 2.0.0 resolution: "fresh@npm:2.0.0" @@ -8733,12 +8535,10 @@ __metadata: languageName: node linkType: hard -"fs-minipass@npm:^2.0.0": - version: 2.1.0 - resolution: "fs-minipass@npm:2.1.0" - dependencies: - minipass: ^3.0.0 - checksum: 1b8d128dae2ac6cc94230cc5ead341ba3e0efaef82dab46a33d171c044caaa6ca001364178d42069b2809c35a1c3c35079a32107c770e9ffab3901b59af8c8b1 +"fresh@npm:~0.5.2": + version: 0.5.2 + resolution: "fresh@npm:0.5.2" + checksum: 13ea8b08f91e669a64e3ba3a20eb79d7ca5379a81f1ff7f4310d54e2320645503cc0c78daedc93dfb6191287295f6479544a649c64d8e41a1c0fb0c221552346 languageName: node linkType: hard @@ -8796,6 +8596,13 @@ __metadata: languageName: node linkType: hard +"generator-function@npm:^2.0.0": + version: 2.0.1 + resolution: "generator-function@npm:2.0.1" + checksum: 3bf87f7b0230de5d74529677e6c3ceb3b7b5d9618b5a22d92b45ce3876defbaf5a77791b25a61b0fa7d13f95675b5ff67a7769f3b9af33f096e34653519e873d + languageName: node + linkType: hard + "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -8810,28 +8617,41 @@ __metadata: languageName: node linkType: hard -"get-east-asian-width@npm:^1.0.0": - version: 1.3.0 - resolution: "get-east-asian-width@npm:1.3.0" - checksum: 757a34c7a46ff385e2775f96f9d3e553f6b6666a8898fb89040d36a1010fba692332772945606a7d4b0f0c6afb84cd394e75d5477c56e1f00f1eb79603b0aecc +"get-east-asian-width@npm:^1.0.0, get-east-asian-width@npm:^1.3.1": + version: 1.4.0 + resolution: "get-east-asian-width@npm:1.4.0" + checksum: 1d9a81a8004f4217ebef5d461875047d269e4b57e039558fd65130877cd4da8e3f61e1c4eada0c8b10e2816c7baf7d5fddb7006f561da13bc6f6dd19c1e964a4 languageName: node linkType: hard -"get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6": - version: 1.2.6 - resolution: "get-intrinsic@npm:1.2.6" +"get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.3.0": + version: 1.3.1 + resolution: "get-intrinsic@npm:1.3.1" dependencies: - call-bind-apply-helpers: ^1.0.1 - dunder-proto: ^1.0.0 + async-function: ^1.0.0 + async-generator-function: ^1.0.0 + call-bind-apply-helpers: ^1.0.2 es-define-property: ^1.0.1 es-errors: ^1.3.0 - es-object-atoms: ^1.0.0 + es-object-atoms: ^1.1.1 function-bind: ^1.1.2 + generator-function: ^2.0.0 + get-proto: ^1.0.1 gopd: ^1.2.0 has-symbols: ^1.1.0 hasown: ^2.0.2 - math-intrinsics: ^1.0.0 - checksum: a7592a0b7f023a2e83c0121fa9449ca83780e370a5feeebe8452119474d148016e43b455049134ae7a683b9b11b93d3f65eac199a0ad452ab740d5f0c299de47 + math-intrinsics: ^1.1.0 + checksum: c02b3b6a445f9cd53e14896303794ac60f9751f58a69099127248abdb0251957174c6524245fc68579dc8e6a35161d3d94c93e665f808274716f4248b269436a + languageName: node + linkType: hard + +"get-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "get-proto@npm:1.0.1" + dependencies: + dunder-proto: ^1.0.1 + es-object-atoms: ^1.0.0 + checksum: 4fc96afdb58ced9a67558698b91433e6b037aaa6f1493af77498d7c85b141382cf223c0e5946f334fb328ee85dfe6edd06d218eaf09556f4bc4ec6005d7f5f7b languageName: node linkType: hard @@ -8845,13 +8665,13 @@ __metadata: linkType: hard "get-uri@npm:^6.0.1": - version: 6.0.4 - resolution: "get-uri@npm:6.0.4" + version: 6.0.5 + resolution: "get-uri@npm:6.0.5" dependencies: basic-ftp: ^5.0.2 data-uri-to-buffer: ^6.0.2 debug: ^4.3.4 - checksum: 7eae81655e0c8cee250d29c189e09030f37a2d37987298325709affb9408de448bf2dc43ee9a59acd21c1f100c3ca711d0446b4e689e9590c25774ecc59f0442 + checksum: aef94dbecde44bc9cd23f5c1b6af5bf772a3d16612c0fc37d3a4056ffd202f2cdd329746d4fdc2124813ea6c8b1c5279f3749d27226a2b161df43dbcb70082e3 languageName: node linkType: hard @@ -8864,7 +8684,7 @@ __metadata: languageName: node linkType: hard -"glob-parent@npm:^6.0.1, glob-parent@npm:^6.0.2": +"glob-parent@npm:^6.0.1": version: 6.0.2 resolution: "glob-parent@npm:6.0.2" dependencies: @@ -8873,6 +8693,15 @@ __metadata: languageName: node linkType: hard +"glob-to-regex.js@npm:^1.0.0, glob-to-regex.js@npm:^1.0.1": + version: 1.2.0 + resolution: "glob-to-regex.js@npm:1.2.0" + peerDependencies: + tslib: 2 + checksum: ed7797dae9469a62f581213fb4e4272a58650896935b3ccd842a3bfafc7845caffc1510e3a02c3fae647d3740b87a51b5bcc7cc621678b9abc663babcfb3088c + languageName: node + linkType: hard + "glob-to-regexp@npm:^0.4.1": version: 0.4.1 resolution: "glob-to-regexp@npm:0.4.1" @@ -8880,33 +8709,14 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": - version: 10.4.5 - resolution: "glob@npm:10.4.5" +"glob@npm:^13.0.0": + version: 13.0.0 + resolution: "glob@npm:13.0.0" dependencies: - foreground-child: ^3.1.0 - jackspeak: ^3.1.2 - minimatch: ^9.0.4 + minimatch: ^10.1.1 minipass: ^7.1.2 - package-json-from-dist: ^1.0.0 - path-scurry: ^1.11.1 - bin: - glob: dist/esm/bin.mjs - checksum: 0bc725de5e4862f9f387fd0f2b274baf16850dcd2714502ccf471ee401803997983e2c05590cb65f9675a3c6f2a58e7a53f9e365704108c6ad3cbf1d60934c4a - languageName: node - linkType: hard - -"globals@npm:^11.1.0": - version: 11.12.0 - resolution: "globals@npm:11.12.0" - checksum: 67051a45eca3db904aee189dfc7cd53c20c7d881679c93f6146ddd4c9f4ab2268e68a919df740d39c71f4445d2b38ee360fc234428baea1dbdfe68bbcb46979e - languageName: node - linkType: hard - -"globals@npm:^15.15.0": - version: 15.15.0 - resolution: "globals@npm:15.15.0" - checksum: a2a92199a112db00562a2f85eeef2a7e3943e171f7f7d9b17dfa9231e35fd612588f3c199d1509ab1757273467e413b08c80424cf6e399e96acdaf93deb3ee88 + path-scurry: ^2.0.0 + checksum: 963730222b0acc85a0d2616c08ba3a5d5b5f33fbf69182791967b8a02245db505577a6fc19836d5d58e1cbbfb414ad4f62f605a0372ab05cd9e6998efe944369 languageName: node linkType: hard @@ -8970,15 +8780,6 @@ __metadata: languageName: node linkType: hard -"hosted-git-info@npm:^8.0.0": - version: 8.0.2 - resolution: "hosted-git-info@npm:8.0.2" - dependencies: - lru-cache: ^10.0.1 - checksum: b66ef2cacfe8a8dae156e86eddebd0b9e220fbdb6fa866e273982ab9e5b273e6cab317e1f344c5e63e15c0c8774beb268691cd3af5a02e4c3ef574115e8e60bf - languageName: node - linkType: hard - "hosted-git-info@npm:^9.0.0": version: 9.0.2 resolution: "hosted-git-info@npm:9.0.2" @@ -9010,21 +8811,21 @@ __metadata: linkType: hard "htmlparser2@npm:^10.0.0": - version: 10.0.0 - resolution: "htmlparser2@npm:10.0.0" + version: 10.1.0 + resolution: "htmlparser2@npm:10.1.0" dependencies: domelementtype: ^2.3.0 domhandler: ^5.0.3 - domutils: ^3.2.1 - entities: ^6.0.0 - checksum: ba81aca5d344437e791ffddf61d498972fc0e7dd2d41f59f920e93aedb64667a0f38fed88e0d81fe23ea5a10825991caa020212fdd72a0dc287ab2aaad95fbf5 + domutils: ^3.2.2 + entities: ^7.0.1 + checksum: 49b8fa62dcd833b89535523c437d04069400e618b22b8dc8cd48bf6ef820752bb026c4f1fc7309d08b6016bfcd3cc0eca4ed48d5eeff4a3e010be19027d51c70 languageName: node linkType: hard "http-cache-semantics@npm:^4.1.1": - version: 4.1.1 - resolution: "http-cache-semantics@npm:4.1.1" - checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 + version: 4.2.0 + resolution: "http-cache-semantics@npm:4.2.0" + checksum: 7a7246ddfce629f96832791176fd643589d954e6f3b49548dadb4290451961237fab8fcea41cd2008fe819d95b41c1e8b97f47d088afc0a1c81705287b4ddbcc languageName: node linkType: hard @@ -9035,20 +8836,7 @@ __metadata: languageName: node linkType: hard -"http-errors@npm:2.0.0": - version: 2.0.0 - resolution: "http-errors@npm:2.0.0" - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - checksum: 9b0a3782665c52ce9dc658a0d1560bcb0214ba5699e4ea15aefb2a496e2ca83db03ebc42e1cce4ac1f413e4e0d2d736a3fd755772c556a9a06853ba2a0b7d920 - languageName: node - linkType: hard - -"http-errors@npm:^2.0.0, http-errors@npm:^2.0.1, http-errors@npm:~2.0.1": +"http-errors@npm:^2.0.0, http-errors@npm:^2.0.1, http-errors@npm:~2.0.0, http-errors@npm:~2.0.1": version: 2.0.1 resolution: "http-errors@npm:2.0.1" dependencies: @@ -9061,22 +8849,23 @@ __metadata: languageName: node linkType: hard -"http-errors@npm:~1.6.2": - version: 1.6.3 - resolution: "http-errors@npm:1.6.3" +"http-errors@npm:~1.8.0": + version: 1.8.1 + resolution: "http-errors@npm:1.8.1" dependencies: depd: ~1.1.2 - inherits: 2.0.3 - setprototypeof: 1.1.0 - statuses: ">= 1.4.0 < 2" - checksum: a9654ee027e3d5de305a56db1d1461f25709ac23267c6dc28cdab8323e3f96caa58a9a6a5e93ac15d7285cee0c2f019378c3ada9026e7fe19c872d695f27de7c + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: ">= 1.5.0 < 2" + toidentifier: 1.0.1 + checksum: d3c7e7e776fd51c0a812baff570bdf06fe49a5dc448b700ab6171b1250e4cf7db8b8f4c0b133e4bfe2451022a5790c1ca6c2cae4094dedd6ac8304a1267f91d2 languageName: node linkType: hard "http-parser-js@npm:>=0.5.1": - version: 0.5.8 - resolution: "http-parser-js@npm:0.5.8" - checksum: 6bbdf2429858e8cf13c62375b0bfb6dc3955ca0f32e58237488bc86cd2378f31d31785fd3ac4ce93f1c74e0189cf8823c91f5cb061696214fd368d2452dc871d + version: 0.5.10 + resolution: "http-parser-js@npm:0.5.10" + checksum: 1038177c5f114860345ce7c19223d2cdd9a103265bd897bab13343c9eff4deef60f7956a674485f1234ffc9b19fb4b97f0c20a5848cfc9ccbf5d3c438d89ae89 languageName: node linkType: hard @@ -9150,15 +8939,6 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:0.4.24": - version: 0.4.24 - resolution: "iconv-lite@npm:0.4.24" - dependencies: - safer-buffer: ">= 2.1.2 < 3" - checksum: bd9f120f5a5b306f0bc0b9ae1edeb1577161503f5f8252a20f1a9e56ef8775c9959fd01c55f2d3a39d9a8abaf3e30c1abeb1895f367dcbbe0a8fd1c9ca01c4f6 - languageName: node - linkType: hard - "iconv-lite@npm:0.6, iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" @@ -9177,6 +8957,15 @@ __metadata: languageName: node linkType: hard +"iconv-lite@npm:~0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" + dependencies: + safer-buffer: ">= 2.1.2 < 3" + checksum: bd9f120f5a5b306f0bc0b9ae1edeb1577161503f5f8252a20f1a9e56ef8775c9959fd01c55f2d3a39d9a8abaf3e30c1abeb1895f367dcbbe0a8fd1c9ca01c4f6 + languageName: node + linkType: hard + "icss-utils@npm:^5.0.0, icss-utils@npm:^5.1.0": version: 5.1.0 resolution: "icss-utils@npm:5.1.0" @@ -9205,19 +8994,19 @@ __metadata: linkType: hard "immutable@npm:^5.0.2": - version: 5.0.3 - resolution: "immutable@npm:5.0.3" - checksum: b2fcfc75aff29634babfcf6afb102111d7bc3858bfc55c17c5ad5eedf11085fe8b72d59fac883c6cfe9b2ec6e72cc184dec88782d5375ab17dc4eb25e3a665ed + version: 5.1.4 + resolution: "immutable@npm:5.1.4" + checksum: 2bddb02594b27e2f37d35c32acf409b77a815e19e2ae7bbffae4b05535965ed3aaf8808255106cb229b7cf0791001bd88efde9cc38e5b32f935992e9b631adf3 languageName: node linkType: hard "import-fresh@npm:^3.3.0": - version: 3.3.0 - resolution: "import-fresh@npm:3.3.0" + version: 3.3.1 + resolution: "import-fresh@npm:3.3.1" dependencies: parent-module: ^1.0.0 resolve-from: ^4.0.0 - checksum: 2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa + checksum: a06b19461b4879cc654d46f8a6244eb55eb053437afd4cbb6613cad6be203811849ed3e4ea038783092879487299fda24af932b86bdfff67c9055ba3612b8c87 languageName: node linkType: hard @@ -9228,13 +9017,6 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2.0.3": - version: 2.0.3 - resolution: "inherits@npm:2.0.3" - checksum: 78cb8d7d850d20a5e9a7f3620db31483aa00ad5f722ce03a55b110e5a723539b3716a3b463e2b96ce3fe286f33afc7c131fa2f91407528ba80cea98a7545d4c0 - languageName: node - linkType: hard - "inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:~2.0.3, inherits@npm:~2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" @@ -9242,13 +9024,20 @@ __metadata: languageName: node linkType: hard -"ini@npm:5.0.0, ini@npm:^5.0.0": +"ini@npm:5.0.0": version: 5.0.0 resolution: "ini@npm:5.0.0" checksum: a1cd2a06bf4d995b072ebe97132d8d50a6630798cc3a1c56d325d7b3aaf1f236b3301816f0079e4d47a9887f08e60a6fb95673f19bcafe4f0f9c4a5b5e30aff4 languageName: node linkType: hard +"ini@npm:^6.0.0": + version: 6.0.0 + resolution: "ini@npm:6.0.0" + checksum: 82640ea788fac082fdf0a4d901654b0d4a32a62524cb9116206d2d66370fb12468af8bcdec0cafc2ceec71eb095919bf07410ce023e205383d3ae4d6c25b3626 + languageName: node + linkType: hard + "internmap@npm:1 - 2": version: 2.0.3 resolution: "internmap@npm:2.0.3" @@ -9263,13 +9052,10 @@ __metadata: languageName: node linkType: hard -"ip-address@npm:^9.0.5": - version: 9.0.5 - resolution: "ip-address@npm:9.0.5" - dependencies: - jsbn: 1.1.0 - sprintf-js: ^1.1.3 - checksum: aa15f12cfd0ef5e38349744e3654bae649a34c3b10c77a674a167e99925d1549486c5b14730eebce9fea26f6db9d5e42097b00aa4f9f612e68c79121c71652dc +"ip-address@npm:^10.0.1": + version: 10.1.0 + resolution: "ip-address@npm:10.1.0" + checksum: 76b1abcdf52a32e2e05ca1f202f3a8ab8547e5651a9233781b330271bd7f1a741067748d71c4cbb9d9906d9f1fa69e7ddc8b4a11130db4534fdab0e908c84e0d languageName: node linkType: hard @@ -9288,9 +9074,9 @@ __metadata: linkType: hard "ipaddr.js@npm:^2.1.0, ipaddr.js@npm:^2.2.0": - version: 2.2.0 - resolution: "ipaddr.js@npm:2.2.0" - checksum: 770ba8451fd9bf78015e8edac0d5abd7a708cbf75f9429ca9147a9d2f3a2d60767cd5de2aab2b1e13ca6e4445bdeff42bf12ef6f151c07a5c6cf8a44328e2859 + version: 2.3.0 + resolution: "ipaddr.js@npm:2.3.0" + checksum: 275602ad56e765d6c4187c1ab1a17d415da7a263e8d3278da5bdb6db147b29c56fac7e98a3f68b05d25e0b515601f1e750c2dd8ec9a871eb93ea094643b84916 languageName: node linkType: hard @@ -9310,16 +9096,7 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.16.0": - version: 2.16.0 - resolution: "is-core-module@npm:2.16.0" - dependencies: - hasown: ^2.0.2 - checksum: 98aa14eaee864c2e86fff4e08813e0da3ca7ac38dd0a43b9f10aeec48bfbc4827e2677349adb626f66921caef7fa9e2745c80b8b7cafe8ac24d46dc8124cc216 - languageName: node - linkType: hard - -"is-core-module@npm:^2.16.1": +"is-core-module@npm:^2.16.0, is-core-module@npm:^2.16.1": version: 2.16.1 resolution: "is-core-module@npm:2.16.1" dependencies: @@ -9359,11 +9136,11 @@ __metadata: linkType: hard "is-fullwidth-code-point@npm:^5.0.0": - version: 5.0.0 - resolution: "is-fullwidth-code-point@npm:5.0.0" + version: 5.1.0 + resolution: "is-fullwidth-code-point@npm:5.1.0" dependencies: - get-east-asian-width: ^1.0.0 - checksum: 8dfb2d2831b9e87983c136f5c335cd9d14c1402973e357a8ff057904612ed84b8cba196319fabedf9aefe4639e14fe3afe9d9966d1d006ebeb40fe1fed4babe5 + get-east-asian-width: ^1.3.1 + checksum: 4700d8a82cb71bd2a2955587b2823c36dc4660eadd4047bfbd070821ddbce8504fc5f9b28725567ecddf405b1e06c6692c9b719f65df6af9ec5262bc11393a6a languageName: node linkType: hard @@ -9395,9 +9172,9 @@ __metadata: linkType: hard "is-network-error@npm:^1.0.0": - version: 1.1.0 - resolution: "is-network-error@npm:1.1.0" - checksum: b2fe6aac07f814a9de275efd05934c832c129e7ba292d27614e9e8eec9e043b7a0bbeaeca5d0916b0f462edbec2aa2eaee974ee0a12ac095040e9515c222c251 + version: 1.3.0 + resolution: "is-network-error@npm:1.3.0" + checksum: 56dc0b8ed9c0bb72202058f172ad0c3121cf68772e8cbba343d3775f6e2ec7877d423cbcea45f4cedcd345de8693de1b52dfe0c6fc15d652c4aa98c2abf0185a languageName: node linkType: hard @@ -9523,19 +9300,6 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^3.1.2": - version: 3.4.3 - resolution: "jackspeak@npm:3.4.3" - dependencies: - "@isaacs/cliui": ^8.0.2 - "@pkgjs/parseargs": ^0.11.0 - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: be31027fc72e7cc726206b9f560395604b82e0fddb46c4cbf9f97d049bcef607491a5afc0699612eaa4213ca5be8fd3e1e7cd187b3040988b65c9489838a7c00 - languageName: node - linkType: hard - "jest-worker@npm:^27.4.5": version: 27.5.1 resolution: "jest-worker@npm:27.5.1" @@ -9547,12 +9311,12 @@ __metadata: languageName: node linkType: hard -"jiti@npm:^1.20.0, jiti@npm:^1.21.6": - version: 1.21.6 - resolution: "jiti@npm:1.21.6" +"jiti@npm:^1.20.0": + version: 1.21.7 + resolution: "jiti@npm:1.21.7" bin: jiti: bin/jiti.js - checksum: 9ea4a70a7bb950794824683ed1c632e2ede26949fbd348e2ba5ec8dc5efa54dc42022d85ae229cadaa60d4b95012e80ea07d625797199b688cc22ab0e8891d32 + checksum: 9cd20dabf82e3a4cceecb746a69381da7acda93d34eed0cdb9c9bdff3bce07e4f2f4a016ca89924392c935297d9aedc58ff9f7d3281bc5293319ad244926e0b7 languageName: node linkType: hard @@ -9572,13 +9336,6 @@ __metadata: languageName: node linkType: hard -"js-base64@npm:^3.7.5": - version: 3.7.7 - resolution: "js-base64@npm:3.7.7" - checksum: d1b02971db9dc0fd35baecfaf6ba499731fb44fe3373e7e1d6681fbd3ba665f29e8d9d17910254ef8104e2cb8b44117fe4202d3dc54c7cafe9ba300fe5433358 - languageName: node - linkType: hard - "js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -9593,18 +9350,7 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^4.1.0": - version: 4.1.0 - resolution: "js-yaml@npm:4.1.0" - dependencies: - argparse: ^2.0.1 - bin: - js-yaml: bin/js-yaml.js - checksum: c7830dfd456c3ef2c6e355cc5a92e6700ceafa1d14bba54497b34a99f0376cecbb3e9ac14d3e5849b426d5a5140709a66237a8c991c675431271c4ce5504151a - languageName: node - linkType: hard - -"js-yaml@npm:^4.1.1": +"js-yaml@npm:^4.1.0, js-yaml@npm:^4.1.1": version: 4.1.1 resolution: "js-yaml@npm:4.1.1" dependencies: @@ -9615,13 +9361,6 @@ __metadata: languageName: node linkType: hard -"jsbn@npm:1.1.0": - version: 1.1.0 - resolution: "jsbn@npm:1.1.0" - checksum: 944f924f2bd67ad533b3850eee47603eed0f6ae425fd1ee8c760f477e8c34a05f144c1bd4f5a5dd1963141dc79a2c55f89ccc5ab77d039e7077f3ad196b64965 - languageName: node - linkType: hard - "jsdom@npm:^27.4.0": version: 27.4.0 resolution: "jsdom@npm:27.4.0" @@ -9664,15 +9403,6 @@ __metadata: languageName: node linkType: hard -"jsesc@npm:~3.0.2": - version: 3.0.2 - resolution: "jsesc@npm:3.0.2" - bin: - jsesc: bin/jsesc - checksum: a36d3ca40574a974d9c2063bf68c2b6141c20da8f2a36bd3279fc802563f35f0527a6c828801295bdfb2803952cf2cf387786c2c90ed564f88d5782475abfe3c - languageName: node - linkType: hard - "json-parse-even-better-errors@npm:^2.3.0, json-parse-even-better-errors@npm:^2.3.1": version: 2.3.1 resolution: "json-parse-even-better-errors@npm:2.3.1" @@ -9680,10 +9410,10 @@ __metadata: languageName: node linkType: hard -"json-parse-even-better-errors@npm:^4.0.0": - version: 4.0.0 - resolution: "json-parse-even-better-errors@npm:4.0.0" - checksum: da1ae7ef0cc9db02972a06a71322f26bdcda5d7f648c23b28ce7f158ba35707461bcbd91945d8aace10d8d79c383b896725c65ffa410242352692328aa9b5edf +"json-parse-even-better-errors@npm:^5.0.0": + version: 5.0.0 + resolution: "json-parse-even-better-errors@npm:5.0.0" + checksum: b5aeaa65e072bc3bda2cb1da50bf1822814b4aa7c568e7c2bed25af89d730f113dcb74393da574c0a32e889eeba4a826db600b8a6ecef917c59c8c6b38f2efaa languageName: node linkType: hard @@ -9710,7 +9440,7 @@ __metadata: languageName: node linkType: hard -"jsonc-parser@npm:3.3.1, jsonc-parser@npm:^3.0.0": +"jsonc-parser@npm:3.3.1": version: 3.3.1 resolution: "jsonc-parser@npm:3.3.1" checksum: 81ef19d98d9c6bd6e4a37a95e2753c51c21705cbeffd895e177f4b542cca9cda5fda12fb942a71a2e824a9132cf119dc2e642e9286386055e1365b5478f49a47 @@ -9733,25 +9463,14 @@ __metadata: languageName: node linkType: hard -"katex@npm:^0.16.0": - version: 0.16.22 - resolution: "katex@npm:0.16.22" - dependencies: - commander: ^8.3.0 - bin: - katex: cli.js - checksum: 66a609b6f3e1a3e8634a03228dcd31cb88b7f39d057cfe5271417bc8eb64b85f256accdbd68f453b5714e4e9546192bad554f75c8b9adb91d6b0a7a93505376b - languageName: node - linkType: hard - -"katex@npm:^0.16.22": - version: 0.16.25 - resolution: "katex@npm:0.16.25" +"katex@npm:^0.16.0, katex@npm:^0.16.22": + version: 0.16.28 + resolution: "katex@npm:0.16.28" dependencies: commander: ^8.3.0 bin: katex: cli.js - checksum: 6c73ffd33018c42656bf220889e30738f84a1e00a0e22300ffbabd559880bb3dad33fd3b5e5fcf62addd79c1b31f7c75fcfa6cc8684de6175ce5e30248cff607 + checksum: b30ce609fe7340f697b0aff0cd8570f3a8d740fc8492a622b15cc19c1953eeb1b7908c0bb9bb0bf050c8c683d0bc8ab2f5ef5271861b21b71f8fc41b939bf6bf languageName: node linkType: hard @@ -9770,8 +9489,8 @@ __metadata: linkType: hard "knip@npm:^5.79.0": - version: 5.79.0 - resolution: "knip@npm:5.79.0" + version: 5.82.1 + resolution: "knip@npm:5.82.1" dependencies: "@nodelib/fs.walk": ^1.2.3 fast-glob: ^3.3.3 @@ -9791,14 +9510,7 @@ __metadata: bin: knip: bin/knip.js knip-bun: bin/knip-bun.js - checksum: e9ca55890dcc534fb1596159f1d00f862df8feee9dd2e63afcbaa9c43350e7dc3350b7a710ffbb7d5c7a1f4a6ced318841d1798e31dfddb9e41b4cf2c357ac2d - languageName: node - linkType: hard - -"kolorist@npm:^1.8.0": - version: 1.8.0 - resolution: "kolorist@npm:1.8.0" - checksum: b056de671acc8a17f1e78d6d46c47dae3e06481eabc9fed213dd9079a7454fd3a7ea1226ec718df81c9208877f7475d038ac27a400958fec278d975839e33643 + checksum: 0a7e4012761903efd85e98e3888253b323f470972ebcfd6dd5993f9da522a36b2c7e7ee172326354131cb9dc476c5499685788af16c684d6458896de009b6a0c languageName: node linkType: hard @@ -9816,12 +9528,12 @@ __metadata: linkType: hard "launch-editor@npm:^2.6.1": - version: 2.9.1 - resolution: "launch-editor@npm:2.9.1" + version: 2.12.0 + resolution: "launch-editor@npm:2.12.0" dependencies: - picocolors: ^1.0.0 - shell-quote: ^1.8.1 - checksum: bed887085a9729cc2ad050329d92a99f4c69bacccf96d1ed8c84670608a3a128a828ba8e9a8a41101c5aea5aea6f79984658e2fd11f6ba85e32e6e1ed16dbb1c + picocolors: ^1.1.1 + shell-quote: ^1.8.3 + checksum: b1aa1b92ef4e720d1edd7f80affb90b2fa1cc2c41641cf80158940698c18a4b6a67e2a7cb060547712e858f0ec1a7c8c39f605e0eb299f516a6184f4e680ffc8 languageName: node linkType: hard @@ -9891,9 +9603,9 @@ __metadata: linkType: hard "libphonenumber-js@npm:^1.12.9": - version: 1.12.9 - resolution: "libphonenumber-js@npm:1.12.9" - checksum: 9d01151ffa1d0f634ebbc4e7d5cde6baa7c53765e162745cb2dd85815e04b42847ff2e4c54fe172121c335c86cd6f5ce9192af62237099213e799de653d5a6dd + version: 1.12.36 + resolution: "libphonenumber-js@npm:1.12.36" + checksum: f39b5ed57bdf76825fd8b3b04f83957f7888b18d5945bad2b2529a35dfedea9d7a706c5ca2dbcafe78fb9b8c20b5cbc7c8568c904a09c8118285bc954cefd5da languageName: node linkType: hard @@ -9911,13 +9623,6 @@ __metadata: languageName: node linkType: hard -"lilconfig@npm:^3.0.0, lilconfig@npm:^3.1.3": - version: 3.1.3 - resolution: "lilconfig@npm:3.1.3" - checksum: 644eb10830350f9cdc88610f71a921f510574ed02424b57b0b3abb66ea725d7a082559552524a842f4e0272c196b88dfe1ff7d35ffcc6f45736777185cd67c9a - languageName: node - linkType: hard - "lines-and-columns@npm:^1.1.6": version: 1.2.4 resolution: "lines-and-columns@npm:1.2.4" @@ -9977,10 +9682,10 @@ __metadata: languageName: node linkType: hard -"loader-runner@npm:^4.2.0": - version: 4.3.0 - resolution: "loader-runner@npm:4.3.0" - checksum: a90e00dee9a16be118ea43fec3192d0b491fe03a32ed48a4132eb61d498f5536a03a1315531c19d284392a8726a4ecad71d82044c28d7f22ef62e029bf761569 +"loader-runner@npm:^4.3.1": + version: 4.3.1 + resolution: "loader-runner@npm:4.3.1" + checksum: 14689a39a79b286d3d15f2199384d6132d62ea707abd6c7e50dc8a1f80c20cbfdd5344f7e6b4a7346974696689ab1a96f8ec7d1e8bf206c5264561502658bd3c languageName: node linkType: hard @@ -10002,17 +9707,6 @@ __metadata: languageName: node linkType: hard -"local-pkg@npm:^1.1.1": - version: 1.1.2 - resolution: "local-pkg@npm:1.1.2" - dependencies: - mlly: ^1.7.4 - pkg-types: ^2.3.0 - quansync: ^0.2.11 - checksum: 69ee8af3236a5f65e17cdcc1e835167d1ff661be42735a39c5d0a2e91252744835a2cb3184a02cbb4275f299955a7e3c4bf7711e9e7b81dd8e0d39bb46375034 - languageName: node - linkType: hard - "locate-path@npm:^6.0.0": version: 6.0.0 resolution: "locate-path@npm:6.0.0" @@ -10022,13 +9716,20 @@ __metadata: languageName: node linkType: hard -"lodash-es@npm:4.17.21, lodash-es@npm:^4.17.21": +"lodash-es@npm:4.17.21": version: 4.17.21 resolution: "lodash-es@npm:4.17.21" checksum: 05cbffad6e2adbb331a4e16fbd826e7faee403a1a04873b82b42c0f22090f280839f85b95393f487c1303c8a3d2a010048bf06151a6cbe03eee4d388fb0a12d2 languageName: node linkType: hard +"lodash-es@npm:^4.17.15, lodash-es@npm:^4.17.21": + version: 4.17.23 + resolution: "lodash-es@npm:4.17.23" + checksum: b1bd1d141bbde8ffc72978e34b364065675806b0ca42ab99477d247fb2ae795faeed81db9283bf18ae1f096c2b6611ec0589e0503fa9724bf82e3dce947bad69 + languageName: node + linkType: hard + "lodash.debounce@npm:^4.0.8": version: 4.0.8 resolution: "lodash.debounce@npm:4.0.8" @@ -10037,9 +9738,9 @@ __metadata: linkType: hard "lodash@npm:^4.17.21": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 + version: 4.17.23 + resolution: "lodash@npm:4.17.23" + checksum: 7daad39758a72872e94651630fbb54ba76868f904211089721a64516ce865506a759d9ad3d8ff22a2a49a50a09db5d27c36f22762d21766e47e3ba918d6d7bab languageName: node linkType: hard @@ -10073,17 +9774,10 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.4.3 - resolution: "lru-cache@npm:10.4.3" - checksum: 6476138d2125387a6d20f100608c2583d415a4f64a0fecf30c9e2dda976614f09cad4baa0842447bd37dd459a7bd27f57d9d8f8ce558805abd487c583f3d774a - languageName: node - linkType: hard - -"lru-cache@npm:^11.1.0, lru-cache@npm:^11.2.4": - version: 11.2.4 - resolution: "lru-cache@npm:11.2.4" - checksum: cb8cf72b80a506593f51880bd5a765380d6d8eb82e99b2fbb2f22fe39e5f2f641d47a2509e74cc294617f32a4e90ae8f6214740fe00bc79a6178854f00419b24 +"lru-cache@npm:^11.0.0, lru-cache@npm:^11.1.0, lru-cache@npm:^11.2.1, lru-cache@npm:^11.2.4, lru-cache@npm:^11.2.5": + version: 11.2.5 + resolution: "lru-cache@npm:11.2.5" + checksum: b3cd18066c81e0540429507036e0a37f860325348f6a85376ed71196e5b893668af410849574c5fb49110bc0afff76b4f87646cb93b2482a315c9e7b8435630f languageName: node linkType: hard @@ -10147,22 +9841,22 @@ __metadata: languageName: node linkType: hard -"make-fetch-happen@npm:^14.0.0, make-fetch-happen@npm:^14.0.1, make-fetch-happen@npm:^14.0.3": - version: 14.0.3 - resolution: "make-fetch-happen@npm:14.0.3" +"make-fetch-happen@npm:^15.0.0, make-fetch-happen@npm:^15.0.1, make-fetch-happen@npm:^15.0.3": + version: 15.0.3 + resolution: "make-fetch-happen@npm:15.0.3" dependencies: - "@npmcli/agent": ^3.0.0 - cacache: ^19.0.1 + "@npmcli/agent": ^4.0.0 + cacache: ^20.0.1 http-cache-semantics: ^4.1.1 minipass: ^7.0.2 - minipass-fetch: ^4.0.0 + minipass-fetch: ^5.0.0 minipass-flush: ^1.0.5 minipass-pipeline: ^1.2.4 negotiator: ^1.0.0 - proc-log: ^5.0.0 + proc-log: ^6.0.0 promise-retry: ^2.0.1 - ssri: ^12.0.0 - checksum: 6fb2fee6da3d98f1953b03d315826b5c5a4ea1f908481afc113782d8027e19f080c85ae998454de4e5f27a681d3ec58d57278f0868d4e0b736f51d396b661691 + ssri: ^13.0.0 + checksum: 4fb9dbb739b33565c85dacdcff7eb9388d8f36f326a59dc13375f01af809c42c48aa5d1f4840ee36623b2461a15476e1e79e4548ca1af30b42e1e324705ac8b3 languageName: node linkType: hard @@ -10184,10 +9878,10 @@ __metadata: languageName: node linkType: hard -"math-intrinsics@npm:^1.0.0": - version: 1.0.0 - resolution: "math-intrinsics@npm:1.0.0" - checksum: ad9edf8b5bec32c78d25163a9343dbe960331c8b4815b099181de7be4681e5abff9642a4b2fbeb3e882d7616567ffc45a5bae59dc8fec417cf5c76d47b92b197 +"math-intrinsics@npm:^1.1.0": + version: 1.1.0 + resolution: "math-intrinsics@npm:1.1.0" + checksum: 0e513b29d120f478c85a70f49da0b8b19bc638975eca466f2eeae0071f3ad00454c621bf66e16dd435896c208e719fc91ad79bbfba4e400fe0b372e7c1c9c9a2 languageName: node linkType: hard @@ -10212,15 +9906,27 @@ __metadata: languageName: node linkType: hard -"memfs@npm:^4.6.0": - version: 4.15.0 - resolution: "memfs@npm:4.15.0" - dependencies: - "@jsonjoy.com/json-pack": ^1.0.3 - "@jsonjoy.com/util": ^1.3.0 - tree-dump: ^1.0.1 +"memfs@npm:^4.43.1, memfs@npm:^4.6.0": + version: 4.56.10 + resolution: "memfs@npm:4.56.10" + dependencies: + "@jsonjoy.com/fs-core": 4.56.10 + "@jsonjoy.com/fs-fsa": 4.56.10 + "@jsonjoy.com/fs-node": 4.56.10 + "@jsonjoy.com/fs-node-builtins": 4.56.10 + "@jsonjoy.com/fs-node-to-fsa": 4.56.10 + "@jsonjoy.com/fs-node-utils": 4.56.10 + "@jsonjoy.com/fs-print": 4.56.10 + "@jsonjoy.com/fs-snapshot": 4.56.10 + "@jsonjoy.com/json-pack": ^1.11.0 + "@jsonjoy.com/util": ^1.9.0 + glob-to-regex.js: ^1.0.1 + thingies: ^2.5.0 + tree-dump: ^1.0.3 tslib: ^2.0.0 - checksum: c9554ede52538d8bca5dc7521cf1c2729f7258e14f8ad5483b4637fb942305845bad76ed619e811beee2c5ad0bc9ff409ef770ab3b70e0b8a8017c4c2163764a + peerDependencies: + tslib: 2 + checksum: 25eb19575721872831384363fa39a5392915399dbd548a2bc872e20d020d502d2d129c77a39199303427f86a8f0c08b978c423eb52c912af0f0e46358d56c762 languageName: node linkType: hard @@ -10253,8 +9959,8 @@ __metadata: linkType: hard "mermaid@npm:^11.10.0": - version: 11.12.1 - resolution: "mermaid@npm:11.12.1" + version: 11.12.2 + resolution: "mermaid@npm:11.12.2" dependencies: "@braintree/sanitize-url": ^7.1.1 "@iconify/utils": ^3.0.1 @@ -10276,7 +9982,7 @@ __metadata: stylis: ^4.3.6 ts-dedent: ^2.2.0 uuid: ^11.1.0 - checksum: db20ce808562e040c311c810f40c0fdcfe566ebc80df5b1cd47699bcd5d00369e0b3884269e024b1e479eb4ab292cc855efa6850211d4c4de3bb704a810eb2fd + checksum: 29069be734b933c513c9676b2937ab46499a387d5cfa48bd252e007962715dfdfdfa912b0812a8f0c07f2c22328f6ea557a2ef7b4d867ce4eb3ed7e089f887ad languageName: node linkType: hard @@ -10287,7 +9993,7 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5, micromatch@npm:^4.0.8": +"micromatch@npm:^4.0.2, micromatch@npm:^4.0.8": version: 4.0.8 resolution: "micromatch@npm:4.0.8" dependencies: @@ -10304,21 +10010,14 @@ __metadata: languageName: node linkType: hard -"mime-db@npm:>= 1.43.0 < 2": - version: 1.53.0 - resolution: "mime-db@npm:1.53.0" - checksum: 3fd9380bdc0b085d0b56b580e4f89ca4fc3b823722310d795c248f0806b9a80afd5d8f4347f015ad943b9ecfa7cc0b71dffa0db96fa776d01a13474821a2c7fb - languageName: node - linkType: hard - -"mime-db@npm:^1.54.0": +"mime-db@npm:>= 1.43.0 < 2, mime-db@npm:^1.54.0": version: 1.54.0 resolution: "mime-db@npm:1.54.0" checksum: e99aaf2f23f5bd607deb08c83faba5dd25cf2fec90a7cc5b92d8260867ee08dab65312e1a589e60093dc7796d41e5fae013268418482f1db4c7d52d0a0960ac9 languageName: node linkType: hard -"mime-types@npm:^2.1.27, mime-types@npm:^2.1.31, mime-types@npm:~2.1.17, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": +"mime-types@npm:^2.1.27, mime-types@npm:^2.1.31, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34, mime-types@npm:~2.1.35": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -10327,7 +10026,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:^3.0.0, mime-types@npm:^3.0.2": +"mime-types@npm:^3.0.0, mime-types@npm:^3.0.1, mime-types@npm:^3.0.2": version: 3.0.2 resolution: "mime-types@npm:3.0.2" dependencies: @@ -10371,7 +10070,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^10.0.3": +"minimatch@npm:^10.0.3, minimatch@npm:^10.1.1": version: 10.1.1 resolution: "minimatch@npm:10.1.1" dependencies: @@ -10380,15 +10079,6 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": - version: 9.0.5 - resolution: "minimatch@npm:9.0.5" - dependencies: - brace-expansion: ^2.0.1 - checksum: 2c035575eda1e50623c731ec6c14f65a85296268f749b9337005210bb2b34e2705f8ef1a358b188f69892286ab99dc42c8fb98a57bde55c8d81b3023c19cea28 - languageName: node - linkType: hard - "minimist@npm:^1.2.8": version: 1.2.8 resolution: "minimist@npm:1.2.8" @@ -10405,9 +10095,9 @@ __metadata: languageName: node linkType: hard -"minipass-fetch@npm:^4.0.0": - version: 4.0.0 - resolution: "minipass-fetch@npm:4.0.0" +"minipass-fetch@npm:^5.0.0": + version: 5.0.0 + resolution: "minipass-fetch@npm:5.0.0" dependencies: encoding: ^0.1.13 minipass: ^7.0.3 @@ -10416,7 +10106,7 @@ __metadata: dependenciesMeta: encoding: optional: true - checksum: 7d59a31011ab9e4d1af6562dd4c4440e425b2baf4c5edbdd2e22fb25a88629e1cdceca39953ff209da504a46021df520f18fd9a519f36efae4750ff724ddadea + checksum: 416645d1e54c09fdfe64ec1676541ac2f6f2af3abc7ad25f2f22c4518535997c1ecd2c0c586ea8a5c6499ad7d8f97671f50ff38488ada54bf61fde309f731379 languageName: node linkType: hard @@ -10456,37 +10146,19 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0": - version: 5.0.0 - resolution: "minipass@npm:5.0.0" - checksum: 425dab288738853fded43da3314a0b5c035844d6f3097a8e3b5b29b328da8f3c1af6fc70618b32c29ff906284cf6406b6841376f21caaadd0793c1d5a6a620ea - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": +"minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": version: 7.1.2 - resolution: "minipass@npm:7.1.2" - checksum: 2bfd325b95c555f2b4d2814d49325691c7bee937d753814861b0b49d5edcda55cbbf22b6b6a60bb91eddac8668771f03c5ff647dcd9d0f798e9548b9cdc46ee3 - languageName: node - linkType: hard - -"minizlib@npm:^2.1.1": - version: 2.1.2 - resolution: "minizlib@npm:2.1.2" - dependencies: - minipass: ^3.0.0 - yallist: ^4.0.0 - checksum: f1fdeac0b07cf8f30fcf12f4b586795b97be856edea22b5e9072707be51fc95d41487faec3f265b42973a304fe3a64acd91a44a3826a963e37b37bafde0212c3 + resolution: "minipass@npm:7.1.2" + checksum: 2bfd325b95c555f2b4d2814d49325691c7bee937d753814861b0b49d5edcda55cbbf22b6b6a60bb91eddac8668771f03c5ff647dcd9d0f798e9548b9cdc46ee3 languageName: node linkType: hard -"minizlib@npm:^3.0.1": - version: 3.0.1 - resolution: "minizlib@npm:3.0.1" +"minizlib@npm:^3.0.1, minizlib@npm:^3.1.0": + version: 3.1.0 + resolution: "minizlib@npm:3.1.0" dependencies: - minipass: ^7.0.4 - rimraf: ^5.0.5 - checksum: da0a53899252380475240c587e52c824f8998d9720982ba5c4693c68e89230718884a209858c156c6e08d51aad35700a3589987e540593c36f6713fe30cd7338 + minipass: ^7.1.2 + checksum: a15e6f0128f514b7d41a1c68ce531155447f4669e32d279bba1c1c071ef6c2abd7e4d4579bb59ccc2ed1531346749665968fdd7be8d83eb6b6ae2fe1f3d370a7 languageName: node linkType: hard @@ -10497,25 +10169,7 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^1.0.3": - version: 1.0.4 - resolution: "mkdirp@npm:1.0.4" - bin: - mkdirp: bin/cmd.js - checksum: a96865108c6c3b1b8e1d5e9f11843de1e077e57737602de1b82030815f311be11f96f09cce59bd5b903d0b29834733e5313f9301e3ed6d6f6fba2eae0df4298f - languageName: node - linkType: hard - -"mkdirp@npm:^3.0.1": - version: 3.0.1 - resolution: "mkdirp@npm:3.0.1" - bin: - mkdirp: dist/cjs/src/bin.js - checksum: 972deb188e8fb55547f1e58d66bd6b4a3623bf0c7137802582602d73e6480c1c2268dcbafbfb1be466e00cc7e56ac514d7fd9334b7cf33e3e2ab547c16f83a8d - languageName: node - linkType: hard - -"mlly@npm:^1.7.4": +"mlly@npm:^1.7.4, mlly@npm:^1.8.0": version: 1.8.0 resolution: "mlly@npm:1.8.0" dependencies: @@ -10590,14 +10244,14 @@ __metadata: linkType: hard "msgpackr@npm:^1.11.2": - version: 1.11.2 - resolution: "msgpackr@npm:1.11.2" + version: 1.11.8 + resolution: "msgpackr@npm:1.11.8" dependencies: msgpackr-extract: ^3.0.2 dependenciesMeta: msgpackr-extract: optional: true - checksum: 53b30ddd68fd98ae95690017787f3b54414191314f3d36329cc01c073ec35fece87c86de731ef521d1f1b8adeb294008184ad0266d3a0e62cf0867dc728dcbd1 + checksum: 3f5a78b835c18fb132b4c8e7494e29e5ca4375c7464953b8926baf1facf30eb848ab3156047b1c3b2a4834fd1195df6b7251edcd207f0f3d6d267a5765658816 languageName: node linkType: hard @@ -10620,17 +10274,6 @@ __metadata: languageName: node linkType: hard -"mz@npm:^2.7.0": - version: 2.7.0 - resolution: "mz@npm:2.7.0" - dependencies: - any-promise: ^1.0.0 - object-assign: ^4.0.1 - thenify-all: ^1.0.0 - checksum: 8427de0ece99a07e9faed3c0c6778820d7543e3776f9a84d22cf0ec0a8eb65f6e9aee9c9d353ff9a105ff62d33a9463c6ca638974cc652ee8140cd1e35951c87 - languageName: node - linkType: hard - "nanoid@npm:^3.3.11": version: 3.3.11 resolution: "nanoid@npm:3.3.11" @@ -10640,15 +10283,6 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.7": - version: 3.3.8 - resolution: "nanoid@npm:3.3.8" - bin: - nanoid: bin/nanoid.cjs - checksum: dfe0adbc0c77e9655b550c333075f51bb28cfc7568afbf3237249904f9c86c9aaaed1f113f0fddddba75673ee31c758c30c43d4414f014a52a7a626efc5958c9 - languageName: node - linkType: hard - "needle@npm:^3.1.0": version: 3.3.1 resolution: "needle@npm:3.3.1" @@ -10709,15 +10343,32 @@ __metadata: languageName: node linkType: hard +"ng2-charts@npm:^8.0.0": + version: 8.0.0 + resolution: "ng2-charts@npm:8.0.0" + dependencies: + lodash-es: ^4.17.15 + tslib: ^2.3.0 + peerDependencies: + "@angular/cdk": ">=19.0.0" + "@angular/common": ">=19.0.0" + "@angular/core": ">=19.0.0" + "@angular/platform-browser": ">=19.0.0" + chart.js: ^3.4.0 || ^4.0.0 + rxjs: ^6.5.3 || ^7.4.0 + checksum: b7dfe6a9525eb5343d9a284c3f90bd9baffb58d388067133db27dceedbed90f26c5a6aea43509373d79e00a15c90ddae1a5975f4da72c0b607432aab84f5dbc2 + languageName: node + linkType: hard + "ngx-cookie-service@npm:^19.0.0": - version: 19.0.0 - resolution: "ngx-cookie-service@npm:19.0.0" + version: 19.1.2 + resolution: "ngx-cookie-service@npm:19.1.2" dependencies: tslib: ^2.8.0 peerDependencies: "@angular/common": ^19.0.0 "@angular/core": ^19.0.0 - checksum: a8476d61a2e96fb44f239410b359a213a6de8bf4e468271ce91c73a775f1b45ad690cb19ecd1af3b38ae36d55e79b2b9f09bca6b637572c2f74b800a4d244ab7 + checksum: 75bc5bf9d3e514fa9a844bd7b24a28f14c397028030d5d7a4ed2881c3bff043b3dbcdb1a3720da12bd052444ba32faa85f1a2b7de9610b6beedefd26bd69a2a6 languageName: node linkType: hard @@ -10754,15 +10405,15 @@ __metadata: linkType: hard "ngx-stripe@npm:^19.0.0": - version: 19.0.0 - resolution: "ngx-stripe@npm:19.0.0" + version: 19.8.0 + resolution: "ngx-stripe@npm:19.8.0" dependencies: tslib: ^2.3.0 peerDependencies: "@angular/common": ">=19.0.0 <20.0.0" "@angular/core": ">=19.0.0 <20.0.0" - "@stripe/stripe-js": ">=5.0.0 <6.0.0" - checksum: 77c0b68bf25b1f5fbcb4edda8bc0a6b369f2e197d0258d61b60d7aac3233b93b6edb9ad6b97edb69efabe6a51a84e0d6a6a12c0d34f8ceed26b2cb9d8492435c + "@stripe/stripe-js": ">=8.0.0 <9.0.0" + checksum: 416f242f3417bbc22a84e5b21682918037616ede1dcc349db48f93a79a417b284eaf9dd6b3e9256617d48606d1d391a9329b9f9d716dfcf573d9b1b943c82ecb languageName: node linkType: hard @@ -10785,9 +10436,9 @@ __metadata: linkType: hard "node-forge@npm:^1": - version: 1.3.1 - resolution: "node-forge@npm:1.3.1" - checksum: 08fb072d3d670599c89a1704b3e9c649ff1b998256737f0e06fbd1a5bf41cae4457ccaee32d95052d80bbafd9ffe01284e078c8071f0267dc9744e51c5ed42a9 + version: 1.3.3 + resolution: "node-forge@npm:1.3.3" + checksum: 045b650d61eeba57588744b7be4671044e83871e2c4dc5d4a38a8eb5af7e55fa790c93ba9db1d1ee14a567d25fde41e97a5132e076cff738622e0916c77b48d2 languageName: node linkType: hard @@ -10804,30 +10455,23 @@ __metadata: languageName: node linkType: hard -"node-gyp@npm:^11.0.0, node-gyp@npm:latest": - version: 11.0.0 - resolution: "node-gyp@npm:11.0.0" +"node-gyp@npm:^12.1.0, node-gyp@npm:latest": + version: 12.2.0 + resolution: "node-gyp@npm:12.2.0" dependencies: env-paths: ^2.2.0 exponential-backoff: ^3.1.1 - glob: ^10.3.10 graceful-fs: ^4.2.6 - make-fetch-happen: ^14.0.3 - nopt: ^8.0.0 - proc-log: ^5.0.0 + make-fetch-happen: ^15.0.0 + nopt: ^9.0.0 + proc-log: ^6.0.0 semver: ^7.3.5 - tar: ^7.4.3 - which: ^5.0.0 + tar: ^7.5.4 + tinyglobby: ^0.2.12 + which: ^6.0.0 bin: node-gyp: bin/node-gyp.js - checksum: d7d5055ccc88177f721c7cd4f8f9440c29a0eb40e7b79dba89ef882ec957975dfc1dcb8225e79ab32481a02016eb13bbc051a913ea88d482d3cbdf2131156af4 - languageName: node - linkType: hard - -"node-releases@npm:^2.0.19": - version: 2.0.19 - resolution: "node-releases@npm:2.0.19" - checksum: 917dbced519f48c6289a44830a0ca6dc944c3ee9243c468ebd8515a41c97c8b2c256edb7f3f750416bc37952cc9608684e6483c7b6c6f39f6bd8d86c52cfe658 + checksum: d4ce0acd08bd41004f45e10cef468f4bd15eaafb3acc388a0c567416e1746dc005cc080b8a3495e4e2ae2eed170a2123ff622c2d6614062f4a839837dcf1dd9d languageName: node linkType: hard @@ -10838,25 +10482,14 @@ __metadata: languageName: node linkType: hard -"nopt@npm:^8.0.0": - version: 8.0.0 - resolution: "nopt@npm:8.0.0" +"nopt@npm:^9.0.0": + version: 9.0.0 + resolution: "nopt@npm:9.0.0" dependencies: - abbrev: ^2.0.0 + abbrev: ^4.0.0 bin: nopt: bin/nopt.js - checksum: 2cfc65e7ee38af2e04aea98f054753b0230011c0eeca4ecf131bd7d25984cbbf6f214586e0ae5dfcc2e830bc0bffa5a7fb28ea8d0b306ffd4ae8ea2d814c1ab3 - languageName: node - linkType: hard - -"normalize-package-data@npm:^7.0.0": - version: 7.0.0 - resolution: "normalize-package-data@npm:7.0.0" - dependencies: - hosted-git-info: ^8.0.0 - semver: ^7.3.5 - validate-npm-package-license: ^3.0.4 - checksum: e355670aa1bfa757cfa380c3ea66ad25e8c62001b44c9fa7a9ea3fa8a69f24259fa3e0614bc9330ba1d16052b4feaa2558f4778d65bc34a1b78f73397a418ec0 + checksum: 7a5d9ab0629eaec1944a95438cc4efa6418ed2834aa8eb21a1bea579a7d8ac3e30120131855376a96ef59ab0e23ad8e0bc94d3349770a95e5cb7119339f7c7fb languageName: node linkType: hard @@ -10874,28 +10507,28 @@ __metadata: languageName: node linkType: hard -"npm-bundled@npm:^4.0.0": - version: 4.0.0 - resolution: "npm-bundled@npm:4.0.0" +"npm-bundled@npm:^5.0.0": + version: 5.0.0 + resolution: "npm-bundled@npm:5.0.0" dependencies: - npm-normalize-package-bin: ^4.0.0 - checksum: 028711cda73d162c01abc39ee2caddacf80c3bfc258092b4112250515f084888780aee6fdfed0dc727be3b4f5d56b8736367485aca19a641255868200860459f + npm-normalize-package-bin: ^5.0.0 + checksum: dd2e7535d6463bb4e65a1126564d0db9a54f6c9c47fee08e9583a611e3c6205626a4fa6ecc6fe7aea178e72787e5e236fdedb318f0defd4355bf5d5534640fca languageName: node linkType: hard -"npm-install-checks@npm:^7.1.0": - version: 7.1.1 - resolution: "npm-install-checks@npm:7.1.1" +"npm-install-checks@npm:^8.0.0": + version: 8.0.0 + resolution: "npm-install-checks@npm:8.0.0" dependencies: semver: ^7.1.1 - checksum: b90cbca3ac34ed2ed0bf05867dc5b4eac45afa626b71ce8b6bf3955c6c7a1e22cbbb4718f5d19b0b19bca89f16a13bf3b6ca191afef12ac6c90120cef70b7f1d + checksum: 7a58a84b676ea7fa8b40dca71c93161f77d9c60f1ac2786c7c502009674ee64058f0c628f8fbbb0bbb247bf4924b535549bdb8956e20c2e5337dee04184b2d4c languageName: node linkType: hard -"npm-normalize-package-bin@npm:^4.0.0": - version: 4.0.0 - resolution: "npm-normalize-package-bin@npm:4.0.0" - checksum: e1a0971e5640bc116c5197f9707d86dc404b6d8e13da2c7ea82baa5583b8da279a3c8607234aa1d733c2baac3b3eba87b156f021f20ae183dc4806530e61675d +"npm-normalize-package-bin@npm:^5.0.0": + version: 5.0.0 + resolution: "npm-normalize-package-bin@npm:5.0.0" + checksum: 969bc042d7bb029b5da7eb733e7642b238e3cb071ad57b56a3f128069bc1a3cbc2a4f4af30ee75b11660c368d60b89811ecd1430cf2ea1a7ff36f30052a4aeda languageName: node linkType: hard @@ -10911,19 +10544,19 @@ __metadata: languageName: node linkType: hard -"npm-package-arg@npm:^12.0.0": - version: 12.0.1 - resolution: "npm-package-arg@npm:12.0.1" +"npm-package-arg@npm:^13.0.0": + version: 13.0.2 + resolution: "npm-package-arg@npm:13.0.2" dependencies: - hosted-git-info: ^8.0.0 - proc-log: ^5.0.0 + hosted-git-info: ^9.0.0 + proc-log: ^6.0.0 semver: ^7.3.5 - validate-npm-package-name: ^6.0.0 - checksum: 01c1c620e07940c9c6c243fc3811f1ce745f217800d9d94982519adac1e283790fcc84183e59b0fe10151bbf9967708891eb58256198b153820d79988db98c32 + validate-npm-package-name: ^7.0.0 + checksum: 2b84c322975403f20716a1e89ee6287edb1122fb1ef95b6840738f46db11d6fd511d1caedb33d64146a146b64aacc3d30596646db298f7e8f99fc6ccd4251f79 languageName: node linkType: hard -"npm-packlist@npm:^10.0.0": +"npm-packlist@npm:^10.0.1": version: 10.0.3 resolution: "npm-packlist@npm:10.0.3" dependencies: @@ -10933,31 +10566,31 @@ __metadata: languageName: node linkType: hard -"npm-pick-manifest@npm:^10.0.0": - version: 10.0.0 - resolution: "npm-pick-manifest@npm:10.0.0" +"npm-pick-manifest@npm:^11.0.1": + version: 11.0.3 + resolution: "npm-pick-manifest@npm:11.0.3" dependencies: - npm-install-checks: ^7.1.0 - npm-normalize-package-bin: ^4.0.0 - npm-package-arg: ^12.0.0 + npm-install-checks: ^8.0.0 + npm-normalize-package-bin: ^5.0.0 + npm-package-arg: ^13.0.0 semver: ^7.3.5 - checksum: 2139bd612ee853d86b6420a223dd19dd562cfc7c875ae27895a2d18a9b980e48fe9e895acf69224010b20d01d00150d8da35569d87f09047cc938927ffa2c282 + checksum: e3247d06d6866f9903ab4dfd92a2dc823ef418fd447fe88d099ec880ffa7ed15837b56f1c77841fb851440a520aa5a1bc810b5309715d49c5d234be35f33c6b4 languageName: node linkType: hard -"npm-registry-fetch@npm:^18.0.0": - version: 18.0.2 - resolution: "npm-registry-fetch@npm:18.0.2" +"npm-registry-fetch@npm:^19.0.0": + version: 19.1.1 + resolution: "npm-registry-fetch@npm:19.1.1" dependencies: - "@npmcli/redact": ^3.0.0 + "@npmcli/redact": ^4.0.0 jsonparse: ^1.3.1 - make-fetch-happen: ^14.0.0 + make-fetch-happen: ^15.0.0 minipass: ^7.0.2 - minipass-fetch: ^4.0.0 + minipass-fetch: ^5.0.0 minizlib: ^3.0.1 - npm-package-arg: ^12.0.0 - proc-log: ^5.0.0 - checksum: 99d11962674f56ebf2e3a4623e486ec45db6cbc2bc3e1678afb3fbe0fe827ab668aeb04ee3e5aea0534e293a6ac98d01fd5a15dab8a3647e36c9c34342ff5211 + npm-package-arg: ^13.0.0 + proc-log: ^6.0.0 + checksum: a8a9ccfabb6ec561ca0c4e24f5a7897c84f674fe9b298356bf822f13f3ecda1e8988dedce0e8d566c4ec970be172faebfa73e8c18cdf75d1f2ac160783d0c6f4 languageName: node linkType: hard @@ -10970,24 +10603,17 @@ __metadata: languageName: node linkType: hard -"object-assign@npm:^4, object-assign@npm:^4.0.1": +"object-assign@npm:^4": version: 4.1.1 resolution: "object-assign@npm:4.1.1" checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f languageName: node linkType: hard -"object-hash@npm:^3.0.0": - version: 3.0.0 - resolution: "object-hash@npm:3.0.0" - checksum: 80b4904bb3857c52cc1bfd0b52c0352532ca12ed3b8a6ff06a90cd209dfda1b95cee059a7625eb9da29537027f68ac4619363491eedb2f5d3dddbba97494fd6c - languageName: node - linkType: hard - "object-inspect@npm:^1.13.3": - version: 1.13.3 - resolution: "object-inspect@npm:1.13.3" - checksum: 8c962102117241e18ea403b84d2521f78291b774b03a29ee80a9863621d88265ffd11d0d7e435c4c2cea0dc2a2fbf8bbc92255737a05536590f2df2e8756f297 + version: 1.13.4 + resolution: "object-inspect@npm:1.13.4" + checksum: 582810c6a8d2ef988ea0a39e69e115a138dad8f42dd445383b394877e5816eb4268489f316a6f74ee9c4e0a984b3eab1028e3e79d62b1ed67c726661d55c7a8b languageName: node linkType: hard @@ -10998,7 +10624,7 @@ __metadata: languageName: node linkType: hard -"on-finished@npm:2.4.1, on-finished@npm:^2.4.1": +"on-finished@npm:^2.4.1, on-finished@npm:~2.4.1": version: 2.4.1 resolution: "on-finished@npm:2.4.1" dependencies: @@ -11007,10 +10633,10 @@ __metadata: languageName: node linkType: hard -"on-headers@npm:~1.0.2": - version: 1.0.2 - resolution: "on-headers@npm:1.0.2" - checksum: 2bf13467215d1e540a62a75021e8b318a6cfc5d4fc53af8e8f84ad98dbcea02d506c6d24180cd62e1d769c44721ba542f3154effc1f7579a8288c9f7873ed8e5 +"on-headers@npm:~1.1.0": + version: 1.1.0 + resolution: "on-headers@npm:1.1.0" + checksum: 98aa64629f986fb8cc4517dd8bede73c980e31208cba97f4442c330959f60ced3dc6214b83420491f5111fc7c4f4343abe2ea62c85f505cf041d67850f238776 languageName: node linkType: hard @@ -11032,7 +10658,7 @@ __metadata: languageName: node linkType: hard -"open@npm:10.2.0": +"open@npm:10.2.0, open@npm:^10.0.3": version: 10.2.0 resolution: "open@npm:10.2.0" dependencies: @@ -11044,18 +10670,6 @@ __metadata: languageName: node linkType: hard -"open@npm:^10.0.3": - version: 10.1.0 - resolution: "open@npm:10.1.0" - dependencies: - default-browser: ^5.2.1 - define-lazy-prop: ^3.0.0 - is-inside-container: ^1.0.0 - is-wsl: ^3.1.0 - checksum: 079b0771616bac13b08129b0300032dc9328d72f345e460dd0416b8a8196a5bdf5e0251fefec8aa2a6a97c736734ac65dd8f1d29ab3fc9a13e85624aa5bc4470 - languageName: node - linkType: hard - "ora@npm:8.2.0": version: 8.2.0 resolution: "ora@npm:8.2.0" @@ -11074,36 +10688,36 @@ __metadata: linkType: hard "ordered-binary@npm:^1.5.3": - version: 1.5.3 - resolution: "ordered-binary@npm:1.5.3" - checksum: 1a118c2ad7b5bcba5c0d512cb702e609779b44f431a7e72974107e4367015f8936e02772012cff92231c2c6872e8f8b35d1829cf7a21d58a795844f162706aec + version: 1.6.1 + resolution: "ordered-binary@npm:1.6.1" + checksum: 88161a4830411a09fe90d4dbada5339770dd7ff9410d778b1ace0c27dfdfedaf53d7f999b277b2c8105046f8221c4d20c29e6fdb15606bd8590ffb86029b2d44 languageName: node linkType: hard "oxc-resolver@npm:^11.15.0": - version: 11.16.2 - resolution: "oxc-resolver@npm:11.16.2" - dependencies: - "@oxc-resolver/binding-android-arm-eabi": 11.16.2 - "@oxc-resolver/binding-android-arm64": 11.16.2 - "@oxc-resolver/binding-darwin-arm64": 11.16.2 - "@oxc-resolver/binding-darwin-x64": 11.16.2 - "@oxc-resolver/binding-freebsd-x64": 11.16.2 - "@oxc-resolver/binding-linux-arm-gnueabihf": 11.16.2 - "@oxc-resolver/binding-linux-arm-musleabihf": 11.16.2 - "@oxc-resolver/binding-linux-arm64-gnu": 11.16.2 - "@oxc-resolver/binding-linux-arm64-musl": 11.16.2 - "@oxc-resolver/binding-linux-ppc64-gnu": 11.16.2 - "@oxc-resolver/binding-linux-riscv64-gnu": 11.16.2 - "@oxc-resolver/binding-linux-riscv64-musl": 11.16.2 - "@oxc-resolver/binding-linux-s390x-gnu": 11.16.2 - "@oxc-resolver/binding-linux-x64-gnu": 11.16.2 - "@oxc-resolver/binding-linux-x64-musl": 11.16.2 - "@oxc-resolver/binding-openharmony-arm64": 11.16.2 - "@oxc-resolver/binding-wasm32-wasi": 11.16.2 - "@oxc-resolver/binding-win32-arm64-msvc": 11.16.2 - "@oxc-resolver/binding-win32-ia32-msvc": 11.16.2 - "@oxc-resolver/binding-win32-x64-msvc": 11.16.2 + version: 11.17.0 + resolution: "oxc-resolver@npm:11.17.0" + dependencies: + "@oxc-resolver/binding-android-arm-eabi": 11.17.0 + "@oxc-resolver/binding-android-arm64": 11.17.0 + "@oxc-resolver/binding-darwin-arm64": 11.17.0 + "@oxc-resolver/binding-darwin-x64": 11.17.0 + "@oxc-resolver/binding-freebsd-x64": 11.17.0 + "@oxc-resolver/binding-linux-arm-gnueabihf": 11.17.0 + "@oxc-resolver/binding-linux-arm-musleabihf": 11.17.0 + "@oxc-resolver/binding-linux-arm64-gnu": 11.17.0 + "@oxc-resolver/binding-linux-arm64-musl": 11.17.0 + "@oxc-resolver/binding-linux-ppc64-gnu": 11.17.0 + "@oxc-resolver/binding-linux-riscv64-gnu": 11.17.0 + "@oxc-resolver/binding-linux-riscv64-musl": 11.17.0 + "@oxc-resolver/binding-linux-s390x-gnu": 11.17.0 + "@oxc-resolver/binding-linux-x64-gnu": 11.17.0 + "@oxc-resolver/binding-linux-x64-musl": 11.17.0 + "@oxc-resolver/binding-openharmony-arm64": 11.17.0 + "@oxc-resolver/binding-wasm32-wasi": 11.17.0 + "@oxc-resolver/binding-win32-arm64-msvc": 11.17.0 + "@oxc-resolver/binding-win32-ia32-msvc": 11.17.0 + "@oxc-resolver/binding-win32-x64-msvc": 11.17.0 dependenciesMeta: "@oxc-resolver/binding-android-arm-eabi": optional: true @@ -11145,7 +10759,7 @@ __metadata: optional: true "@oxc-resolver/binding-win32-x64-msvc": optional: true - checksum: 3451b7b0ed5ffe3712640442f7d26cc7cc7584efed4ea0afb73cbb7fcd6df1fc267481ec52c504b11b1fe920b1b7629b7e6e1d3375b4db585f6589170a1e815c + checksum: 6f7dbf3e22970545424ccbfe67c334eff43462d4e7e291a87ce1a7b781a2a6602e08fb63e5f78317041a749ec837e39747e0303a087200a55dd68dd3d4113b57 languageName: node linkType: hard @@ -11168,9 +10782,9 @@ __metadata: linkType: hard "p-map@npm:^7.0.2": - version: 7.0.3 - resolution: "p-map@npm:7.0.3" - checksum: 8c92d533acf82f0d12f7e196edccff773f384098bbb048acdd55a08778ce4fc8889d8f1bde72969487bd96f9c63212698d79744c20bedfce36c5b00b46d369f8 + version: 7.0.4 + resolution: "p-map@npm:7.0.4" + checksum: 4be2097e942f2fd3a4f4b0c6585c721f23851de8ad6484d20c472b3ea4937d5cd9a59914c832b1bceac7bf9d149001938036b82a52de0bc381f61ff2d35d26a5 languageName: node linkType: hard @@ -11186,8 +10800,8 @@ __metadata: linkType: hard "pac-proxy-agent@npm:^7.1.0": - version: 7.1.0 - resolution: "pac-proxy-agent@npm:7.1.0" + version: 7.2.0 + resolution: "pac-proxy-agent@npm:7.2.0" dependencies: "@tootallnate/quickjs-emscripten": ^0.23.0 agent-base: ^7.1.2 @@ -11197,7 +10811,7 @@ __metadata: https-proxy-agent: ^7.0.6 pac-resolver: ^7.0.1 socks-proxy-agent: ^8.0.5 - checksum: 0ed8ebca239b5c78f7c5039ec0e33aaf6ce8de2fb53d00996b5b7b362e655af9793721008ddf56c4b1d30fb5202b2cb5baee97e374ed1285c0cfb5be7c4574a5 + checksum: 099c1bc8944da6a98e8b7de1fbf23e4014bc3063f66a7c29478bd852c1162e1d086a4f80f874f40961ebd5c516e736aed25852db97b79360cbdcc9db38086981 languageName: node linkType: hard @@ -11211,44 +10825,37 @@ __metadata: languageName: node linkType: hard -"package-json-from-dist@npm:^1.0.0": - version: 1.0.1 - resolution: "package-json-from-dist@npm:1.0.1" - checksum: 58ee9538f2f762988433da00e26acc788036914d57c71c246bf0be1b60cdbd77dd60b6a3e1a30465f0b248aeb80079e0b34cb6050b1dfa18c06953bb1cbc7602 - languageName: node - linkType: hard - "package-manager-detector@npm:^1.3.0": - version: 1.5.0 - resolution: "package-manager-detector@npm:1.5.0" - checksum: 7ed3ced86037c3b9ab1609168bd5b69808c32197bd4e9ff3f6b6157dad404aedcf495e3c5fd0fa480b5af3ef5406a7b8e01f87af3035a843bd31eda13adf5a7d + version: 1.6.0 + resolution: "package-manager-detector@npm:1.6.0" + checksum: 154d55225e70e32582f59b5d4a46d25716f0730a14d7e4b6f0fd76c870c720cc6f448d2becca06a15f2042492f0293cf26e5ad8fcd85d0eab0af3b9b46c0b43a languageName: node linkType: hard -"pacote@npm:21.0.0": - version: 21.0.0 - resolution: "pacote@npm:21.0.0" +"pacote@npm:21.0.4": + version: 21.0.4 + resolution: "pacote@npm:21.0.4" dependencies: - "@npmcli/git": ^6.0.0 - "@npmcli/installed-package-contents": ^3.0.0 - "@npmcli/package-json": ^6.0.0 - "@npmcli/promise-spawn": ^8.0.0 - "@npmcli/run-script": ^9.0.0 - cacache: ^19.0.0 + "@npmcli/git": ^7.0.0 + "@npmcli/installed-package-contents": ^4.0.0 + "@npmcli/package-json": ^7.0.0 + "@npmcli/promise-spawn": ^9.0.0 + "@npmcli/run-script": ^10.0.0 + cacache: ^20.0.0 fs-minipass: ^3.0.0 minipass: ^7.0.2 - npm-package-arg: ^12.0.0 - npm-packlist: ^10.0.0 - npm-pick-manifest: ^10.0.0 - npm-registry-fetch: ^18.0.0 - proc-log: ^5.0.0 + npm-package-arg: ^13.0.0 + npm-packlist: ^10.0.1 + npm-pick-manifest: ^11.0.1 + npm-registry-fetch: ^19.0.0 + proc-log: ^6.0.0 promise-retry: ^2.0.1 - sigstore: ^3.0.0 - ssri: ^12.0.0 - tar: ^6.1.11 + sigstore: ^4.0.0 + ssri: ^13.0.0 + tar: ^7.4.3 bin: pacote: bin/index.js - checksum: 46e1605902cbbf8979e770bff2dbf8d84206b9432fe5baab328c477cc0944bbe9ad1e5aff4332099fdcb2014209c540e40fd265fcaa5521c0b37c25c763af9de + checksum: 09e86b71376cbc2d8089e3028d52b6ba41cb034f7f1d2a0a7f8958376eba36426ec75424b94d04672dcfb2fa2fe2120e0ac1dd6c61d64a2b8fd438a0346cc67a languageName: node linkType: hard @@ -11309,7 +10916,7 @@ __metadata: languageName: node linkType: hard -"parseurl@npm:^1.3.3, parseurl@npm:~1.3.2, parseurl@npm:~1.3.3": +"parseurl@npm:^1.3.3, parseurl@npm:~1.3.3": version: 1.3.3 resolution: "parseurl@npm:1.3.3" checksum: 407cee8e0a3a4c5cd472559bca8b6a45b82c124e9a4703302326e9ab60fc1081442ada4e02628efef1eb16197ddc7f8822f5a91fd7d7c86b51f530aedb17dfa2 @@ -11344,20 +10951,13 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.11.1": - version: 1.11.1 - resolution: "path-scurry@npm:1.11.1" +"path-scurry@npm:^2.0.0": + version: 2.0.1 + resolution: "path-scurry@npm:2.0.1" dependencies: - lru-cache: ^10.2.0 - minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - checksum: 890d5abcd593a7912dcce7cf7c6bf7a0b5648e3dee6caf0712c126ca0a65c7f3d7b9d769072a4d1baf370f61ce493ab5b038d59988688e0c5f3f646ee3c69023 - languageName: node - linkType: hard - -"path-to-regexp@npm:0.1.12": - version: 0.1.12 - resolution: "path-to-regexp@npm:0.1.12" - checksum: ab237858bee7b25ecd885189f175ab5b5161e7b712b360d44f5c4516b8d271da3e4bf7bf0a7b9153ecb04c7d90ce8ff5158614e1208819cf62bac2b08452722e + lru-cache: ^11.0.0 + minipass: ^7.1.2 + checksum: a022c6c38fed836079d03f96540eafd4cd989acf287b99613c82300107f366e889513ad8b671a2039a9d251122621f9c6fa649f0bd4d50acf95a6943a6692dbf languageName: node linkType: hard @@ -11368,6 +10968,13 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:~0.1.12": + version: 0.1.12 + resolution: "path-to-regexp@npm:0.1.12" + checksum: ab237858bee7b25ecd885189f175ab5b5161e7b712b360d44f5c4516b8d271da3e4bf7bf0a7b9153ecb04c7d90ce8ff5158614e1208819cf62bac2b08452722e + languageName: node + linkType: hard + "pathe@npm:^2.0.1, pathe@npm:^2.0.3": version: 2.0.3 resolution: "pathe@npm:2.0.3" @@ -11389,7 +10996,7 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:1.1.1, picocolors@npm:^1.0.0, picocolors@npm:^1.1.0, picocolors@npm:^1.1.1": +"picocolors@npm:1.1.1, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 @@ -11410,13 +11017,6 @@ __metadata: languageName: node linkType: hard -"pify@npm:^2.3.0": - version: 2.3.0 - resolution: "pify@npm:2.3.0" - checksum: 9503aaeaf4577acc58642ad1d25c45c6d90288596238fb68f82811c08104c800e5a7870398e9f015d82b44ecbcbef3dc3d4251a1cbb582f6e5959fe09884b2ba - languageName: node - linkType: hard - "pify@npm:^4.0.1": version: 4.0.1 resolution: "pify@npm:4.0.1" @@ -11424,13 +11024,6 @@ __metadata: languageName: node linkType: hard -"pirates@npm:^4.0.1": - version: 4.0.6 - resolution: "pirates@npm:4.0.6" - checksum: 46a65fefaf19c6f57460388a5af9ab81e3d7fd0e7bc44ca59d753cb5c4d0df97c6c6e583674869762101836d68675f027d60f841c105d72734df9dfca97cbcc6 - languageName: node - linkType: hard - "piscina@npm:5.1.3": version: 5.1.3 resolution: "piscina@npm:5.1.3" @@ -11461,38 +11054,27 @@ __metadata: languageName: node linkType: hard -"pkg-types@npm:^2.3.0": - version: 2.3.0 - resolution: "pkg-types@npm:2.3.0" - dependencies: - confbox: ^0.2.2 - exsolve: ^1.0.7 - pathe: ^2.0.3 - checksum: 33c30b442662a0f2b62fd16f39ae2beeb4cdf3511699e574765b7451e179937847de6e696bbab50bfbd41d2c2e4a99b61ebc7078abf91ea8573a7f16cc11d26a - languageName: node - linkType: hard - -"playwright-core@npm:1.57.0": - version: 1.57.0 - resolution: "playwright-core@npm:1.57.0" +"playwright-core@npm:1.58.1": + version: 1.58.1 + resolution: "playwright-core@npm:1.58.1" bin: playwright-core: cli.js - checksum: 960e80d6ec06305b11a3ca9e78e8e4201cc17f37dd37279cb6fece4df43d74bf589833f4f94535fadd284b427f98c5f1cf09368e22f0f00b6a9477571ce6b03b + checksum: 8c74e1cb6f2fb5bec038704efd35332f99d6f6a239be5792fe23416575433ff52082a22295758783f1461a0a8dc87638ef9f6ecdb811dbcb4c850532ecdec359 languageName: node linkType: hard "playwright@npm:^1.57.0": - version: 1.57.0 - resolution: "playwright@npm:1.57.0" + version: 1.58.1 + resolution: "playwright@npm:1.58.1" dependencies: fsevents: 2.3.2 - playwright-core: 1.57.0 + playwright-core: 1.58.1 dependenciesMeta: fsevents: optional: true bin: playwright: cli.js - checksum: 176fd9fd890f390e0aa00d42697b70072d534243b15467d9430f3af329e77b3225b67a0afa12ea76fb440300dabd92d4cf040baf5edceee8eeff0ee1590ae5b7 + checksum: 0dfcfded17a1bc9a0e48044582e31809c65c51c30b3c8cfd4dfd4e7ff3688065af2d071568095dd0aadbeca2eee82eccb91081f485e9fe2026994d3834216d86 languageName: node linkType: hard @@ -11520,48 +11102,6 @@ __metadata: languageName: node linkType: hard -"postcss-import@npm:^15.1.0": - version: 15.1.0 - resolution: "postcss-import@npm:15.1.0" - dependencies: - postcss-value-parser: ^4.0.0 - read-cache: ^1.0.0 - resolve: ^1.1.7 - peerDependencies: - postcss: ^8.0.0 - checksum: 7bd04bd8f0235429009d0022cbf00faebc885de1d017f6d12ccb1b021265882efc9302006ba700af6cab24c46bfa2f3bc590be3f9aee89d064944f171b04e2a3 - languageName: node - linkType: hard - -"postcss-js@npm:^4.0.1": - version: 4.0.1 - resolution: "postcss-js@npm:4.0.1" - dependencies: - camelcase-css: ^2.0.1 - peerDependencies: - postcss: ^8.4.21 - checksum: 5c1e83efeabeb5a42676193f4357aa9c88f4dc1b3c4a0332c132fe88932b33ea58848186db117cf473049fc233a980356f67db490bd0a7832ccba9d0b3fd3491 - languageName: node - linkType: hard - -"postcss-load-config@npm:^4.0.2": - version: 4.0.2 - resolution: "postcss-load-config@npm:4.0.2" - dependencies: - lilconfig: ^3.0.0 - yaml: ^2.3.4 - peerDependencies: - postcss: ">=8.0.9" - ts-node: ">=9.0.0" - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true - checksum: 7c27dd3801db4eae207a5116fed2db6b1ebb780b40c3dd62a3e57e087093a8e6a14ee17ada729fee903152d6ef4826c6339eb135bee6208e0f3140d7e8090185 - languageName: node - linkType: hard - "postcss-loader@npm:8.1.1": version: 8.1.1 resolution: "postcss-loader@npm:8.1.1" @@ -11633,45 +11173,24 @@ __metadata: languageName: node linkType: hard -"postcss-nested@npm:^6.2.0": - version: 6.2.0 - resolution: "postcss-nested@npm:6.2.0" - dependencies: - postcss-selector-parser: ^6.1.1 - peerDependencies: - postcss: ^8.2.14 - checksum: 2c86ecf2d0ce68f27c87c7e24ae22dc6dd5515a89fcaf372b2627906e11f5c1f36e4a09e4c15c20fd4a23d628b3d945c35839f44496fbee9a25866258006671b - languageName: node - linkType: hard - -"postcss-selector-parser@npm:^6.1.1, postcss-selector-parser@npm:^6.1.2": - version: 6.1.2 - resolution: "postcss-selector-parser@npm:6.1.2" - dependencies: - cssesc: ^3.0.0 - util-deprecate: ^1.0.2 - checksum: ce9440fc42a5419d103f4c7c1847cb75488f3ac9cbe81093b408ee9701193a509f664b4d10a2b4d82c694ee7495e022f8f482d254f92b7ffd9ed9dea696c6f84 - languageName: node - linkType: hard - "postcss-selector-parser@npm:^7.0.0": - version: 7.0.0 - resolution: "postcss-selector-parser@npm:7.0.0" + version: 7.1.1 + resolution: "postcss-selector-parser@npm:7.1.1" dependencies: cssesc: ^3.0.0 util-deprecate: ^1.0.2 - checksum: f906b7449fcbe9fa6ae739b6fc324ee3c6201aaf5224f26da27de64ccba68d878d734dd182a467881e463f7ede08972d0129b0cc4d6b671d78c6492cddcef154 + checksum: 36d71bd8e1c9db9c3d4ecefd3f8c30aace141a3a1a266473bc9a1b7a0c1c2dfbaef2ac20cc8ea287b17131cbb3690c1c0fe7a4d9272db9f09b136da2413bc3ea languageName: node linkType: hard -"postcss-value-parser@npm:^4.0.0, postcss-value-parser@npm:^4.1.0, postcss-value-parser@npm:^4.2.0": +"postcss-value-parser@npm:^4.1.0, postcss-value-parser@npm:^4.2.0": version: 4.2.0 resolution: "postcss-value-parser@npm:4.2.0" checksum: 819ffab0c9d51cf0acbabf8996dffbfafbafa57afc0e4c98db88b67f2094cb44488758f06e5da95d7036f19556a4a732525e84289a425f4f6fd8e412a9d7442f languageName: node linkType: hard -"postcss@npm:8.5.6, postcss@npm:^8.4.49, postcss@npm:^8.5.6": +"postcss@npm:8.5.6, postcss@npm:^8.2.14, postcss@npm:^8.4.33, postcss@npm:^8.4.49, postcss@npm:^8.5.6": version: 8.5.6 resolution: "postcss@npm:8.5.6" dependencies: @@ -11682,17 +11201,6 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.2.14, postcss@npm:^8.4.33, postcss@npm:^8.4.47": - version: 8.4.49 - resolution: "postcss@npm:8.4.49" - dependencies: - nanoid: ^3.3.7 - picocolors: ^1.1.1 - source-map-js: ^1.2.1 - checksum: eb5d6cbdca24f50399aafa5d2bea489e4caee4c563ea1edd5a2485bc5f84e9ceef3febf170272bc83a99c31d23a316ad179213e853f34c2a7a8ffa534559d63a - languageName: node - linkType: hard - "postgres-interval@npm:^4.0.2": version: 4.0.2 resolution: "postgres-interval@npm:4.0.2" @@ -11737,7 +11245,7 @@ __metadata: languageName: node linkType: hard -"proc-log@npm:^6.0.0": +"proc-log@npm:^6.0.0, proc-log@npm:^6.1.0": version: 6.1.0 resolution: "proc-log@npm:6.1.0" checksum: ac450ff8244e95b0c9935b52d629fef92ae69b7e39aea19972a8234259614d644402dd62ce9cb094f4a637d8a4514cba90c1456ad785a40ad5b64d502875a817 @@ -11758,13 +11266,6 @@ __metadata: languageName: node linkType: hard -"promise-inflight@npm:^1.0.1": - version: 1.0.1 - resolution: "promise-inflight@npm:1.0.1" - checksum: 22749483091d2c594261517f4f80e05226d4d5ecc1fc917e1886929da56e22b5718b7f2a75f3807e7a7d471bc3be2907fe92e6e8f373ddf5c64bae35b5af3981 - languageName: node - linkType: hard - "promise-retry@npm:^2.0.1": version: 2.0.1 resolution: "promise-retry@npm:2.0.1" @@ -11775,17 +11276,6 @@ __metadata: languageName: node linkType: hard -"proper-lockfile@npm:^4.1.2": - version: 4.1.2 - resolution: "proper-lockfile@npm:4.1.2" - dependencies: - graceful-fs: ^4.2.4 - retry: ^0.12.0 - signal-exit: ^3.0.2 - checksum: 00078ee6a61c216a56a6140c7d2a98c6c733b3678503002dc073ab8beca5d50ca271de4c85fca13b9b8ee2ff546c36674d1850509b84a04a5d0363bcb8638939 - languageName: node - linkType: hard - "proxy-addr@npm:^2.0.7, proxy-addr@npm:~2.0.7": version: 2.0.7 resolution: "proxy-addr@npm:2.0.7" @@ -11827,12 +11317,12 @@ __metadata: linkType: hard "pump@npm:^3.0.0": - version: 3.0.2 - resolution: "pump@npm:3.0.2" + version: 3.0.3 + resolution: "pump@npm:3.0.3" dependencies: end-of-stream: ^1.1.0 once: ^1.3.1 - checksum: e0c4216874b96bd25ddf31a0b61a5613e26cc7afa32379217cf39d3915b0509def3565f5f6968fafdad2894c8bbdbd67d340e84f3634b2a29b950cffb6442d9f + checksum: 52843fc933b838c0330f588388115a1b28ef2a5ffa7774709b142e35431e8ab0c2edec90de3fa34ebb72d59fef854f151eea7dfc211b6dcf586b384556bd2f39 languageName: node linkType: hard @@ -11843,47 +11333,38 @@ __metadata: languageName: node linkType: hard -"puppeteer-core@npm:24.29.1": - version: 24.29.1 - resolution: "puppeteer-core@npm:24.29.1" +"puppeteer-core@npm:24.36.1": + version: 24.36.1 + resolution: "puppeteer-core@npm:24.36.1" dependencies: - "@puppeteer/browsers": 2.10.13 - chromium-bidi: 10.5.1 + "@puppeteer/browsers": 2.11.2 + chromium-bidi: 13.0.1 debug: ^4.4.3 - devtools-protocol: 0.0.1521046 + devtools-protocol: 0.0.1551306 typed-query-selector: ^2.12.0 - webdriver-bidi-protocol: 0.3.8 - ws: ^8.18.3 - checksum: 8317c761e912bf691203ad8aa6d4482f943f82b76baacd8ab8012e1b01d7f22298801bc2544fa9a92f329319dbe66ba980a1eda09aee049ba28da87687aa592f + webdriver-bidi-protocol: 0.4.0 + ws: ^8.19.0 + checksum: 00221534c72394b825b645716751b002279da36dc9067b2e6801c0dc095f7c32a797ed39b9a5f129eb6f74acdb86ece3be95903dc7693da667f443ff33b97b7b languageName: node linkType: hard "puppeteer@npm:^24.29.1": - version: 24.29.1 - resolution: "puppeteer@npm:24.29.1" + version: 24.36.1 + resolution: "puppeteer@npm:24.36.1" dependencies: - "@puppeteer/browsers": 2.10.13 - chromium-bidi: 10.5.1 + "@puppeteer/browsers": 2.11.2 + chromium-bidi: 13.0.1 cosmiconfig: ^9.0.0 - devtools-protocol: 0.0.1521046 - puppeteer-core: 24.29.1 + devtools-protocol: 0.0.1551306 + puppeteer-core: 24.36.1 typed-query-selector: ^2.12.0 bin: puppeteer: lib/cjs/puppeteer/node/cli.js - checksum: a4bbd3f1178f3197767d9bf01c1cb12727520bdc834a19aac17e1850b9ee2b7f4184166dc407865a0d75e2c46010342cc9aad979d4898e274e8777df8dfac3dd - languageName: node - linkType: hard - -"qs@npm:6.13.0": - version: 6.13.0 - resolution: "qs@npm:6.13.0" - dependencies: - side-channel: ^1.0.6 - checksum: e9404dc0fc2849245107108ce9ec2766cde3be1b271de0bf1021d049dc5b98d1a2901e67b431ac5509f865420a7ed80b7acb3980099fe1c118a1c5d2e1432ad8 + checksum: 3efb73a448099e12bf57217d031f072cb41eeaa4517d0276b2f2e504e40675a61295d09f5209d8a59b2d3e6dc9e4baf84cf350cf60bd7284c8b0f4432aecc0fd languageName: node linkType: hard -"qs@npm:^6.14.0, qs@npm:^6.14.1": +"qs@npm:^6.14.0, qs@npm:^6.14.1, qs@npm:~6.14.0": version: 6.14.1 resolution: "qs@npm:6.14.1" dependencies: @@ -11892,13 +11373,6 @@ __metadata: languageName: node linkType: hard -"quansync@npm:^0.2.11": - version: 0.2.11 - resolution: "quansync@npm:0.2.11" - checksum: af484ed433f752c092d278232f68a6643e2cf0193f95ec60c84245e1f3662ef64da90f8fb1bc57dd407362ff181f246a9304ba53725dd7122f45c4a839f85a61 - languageName: node - linkType: hard - "query-string@npm:8.1.0": version: 8.1.0 resolution: "query-string@npm:8.1.0" @@ -11917,13 +11391,6 @@ __metadata: languageName: node linkType: hard -"queue-tick@npm:^1.0.1": - version: 1.0.1 - resolution: "queue-tick@npm:1.0.1" - checksum: 57c3292814b297f87f792fbeb99ce982813e4e54d7a8bdff65cf53d5c084113913289d4a48ec8bbc964927a74b847554f9f4579df43c969a6c8e0f026457ad01 - languageName: node - linkType: hard - "randombytes@npm:^2.1.0": version: 2.1.0 resolution: "randombytes@npm:2.1.0" @@ -11940,18 +11407,6 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:2.5.2": - version: 2.5.2 - resolution: "raw-body@npm:2.5.2" - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - checksum: ba1583c8d8a48e8fbb7a873fdbb2df66ea4ff83775421bfe21ee120140949ab048200668c47d9ae3880012f6e217052690628cf679ddfbd82c9fc9358d574676 - languageName: node - linkType: hard - "raw-body@npm:^3.0.0, raw-body@npm:^3.0.1": version: 3.0.2 resolution: "raw-body@npm:3.0.2" @@ -11964,6 +11419,18 @@ __metadata: languageName: node linkType: hard +"raw-body@npm:~2.5.3": + version: 2.5.3 + resolution: "raw-body@npm:2.5.3" + dependencies: + bytes: ~3.1.2 + http-errors: ~2.0.1 + iconv-lite: ~0.4.24 + unpipe: ~1.0.0 + checksum: 16aa51e504318ebeef7f84a4d884c0f273cb0b7f3f14ea88788f92f5f488870617c97d4f886e84f119f21a2d6cdda3c4554821f8b18ed6be0d731ecb5a063d2a + languageName: node + linkType: hard + "react-is@npm:^17.0.1": version: 17.0.2 resolution: "react-is@npm:17.0.2" @@ -11971,15 +11438,6 @@ __metadata: languageName: node linkType: hard -"read-cache@npm:^1.0.0": - version: 1.0.0 - resolution: "read-cache@npm:1.0.0" - dependencies: - pify: ^2.3.0 - checksum: cffc728b9ede1e0667399903f9ecaf3789888b041c46ca53382fa3a06303e5132774dc0a96d0c16aa702dbac1ea0833d5a868d414f5ab2af1e1438e19e6657c6 - languageName: node - linkType: hard - "readable-stream@npm:^2.0.1": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" @@ -12007,9 +11465,9 @@ __metadata: linkType: hard "readdirp@npm:^4.0.1": - version: 4.0.2 - resolution: "readdirp@npm:4.0.2" - checksum: 309376e717f94fb7eb61bec21e2603243a9e2420cd2e9bf94ddf026aefea0d7377ed1a62f016d33265682e44908049a55c3cfc2307450a1421654ea008489b39 + version: 4.1.2 + resolution: "readdirp@npm:4.1.2" + checksum: 3242ee125422cb7c0e12d51452e993f507e6ed3d8c490bc8bf3366c5cdd09167562224e429b13e9cb2b98d4b8b2b11dc100d3c73883aa92d657ade5a21ded004 languageName: node linkType: hard @@ -12029,15 +11487,6 @@ __metadata: languageName: node linkType: hard -"regenerate-unicode-properties@npm:^10.2.0": - version: 10.2.0 - resolution: "regenerate-unicode-properties@npm:10.2.0" - dependencies: - regenerate: ^1.4.2 - checksum: d5c5fc13f8b8d7e16e791637a4bfef741f8d70e267d51845ee7d5404a32fa14c75b181c4efba33e4bff8b0000a2f13e9773593713dfe5b66597df4259275ce63 - languageName: node - linkType: hard - "regenerate-unicode-properties@npm:^10.2.2": version: 10.2.2 resolution: "regenerate-unicode-properties@npm:10.2.2" @@ -12054,31 +11503,10 @@ __metadata: languageName: node linkType: hard -"regenerator-runtime@npm:^0.14.0": - version: 0.14.1 - resolution: "regenerator-runtime@npm:0.14.1" - checksum: 9f57c93277b5585d3c83b0cf76be47b473ae8c6d9142a46ce8b0291a04bb2cf902059f0f8445dcabb3fb7378e5fe4bb4ea1e008876343d42e46d3b484534ce38 - languageName: node - linkType: hard - "regex-parser@npm:^2.2.11": - version: 2.3.0 - resolution: "regex-parser@npm:2.3.0" - checksum: bcd1eb7e9b0775b6f44928ceb0280ad5b6e4da91e1070d3e9a653fcf72d2d04873c44190fb569141b6897fe94e9514fee1f3ac7ba112ccd9c9b5ad6eabab6bbd - languageName: node - linkType: hard - -"regexpu-core@npm:^6.2.0": - version: 6.2.0 - resolution: "regexpu-core@npm:6.2.0" - dependencies: - regenerate: ^1.4.2 - regenerate-unicode-properties: ^10.2.0 - regjsgen: ^0.8.0 - regjsparser: ^0.12.0 - unicode-match-property-ecmascript: ^2.0.0 - unicode-match-property-value-ecmascript: ^2.1.0 - checksum: 67d3c4a3f6c99bc80b5d690074a27e6f675be1c1739f8a9acf028fbc36f1a468472574ea65e331e217995198ba4404d7878f3cb3739a73552dd3c70d3fb7f8e6 + version: 2.3.1 + resolution: "regex-parser@npm:2.3.1" + checksum: 37d5549040782207b98a5c007b739f85bf43f70249cbf813954d3fab370b93f3c8029534c62ca7c56e7a61e24848118b1bae15668b80ab7e67b4bb98465d54cc languageName: node linkType: hard @@ -12103,17 +11531,6 @@ __metadata: languageName: node linkType: hard -"regjsparser@npm:^0.12.0": - version: 0.12.0 - resolution: "regjsparser@npm:0.12.0" - dependencies: - jsesc: ~3.0.2 - bin: - regjsparser: bin/parser - checksum: 094b55b0ab3e1fd58f8ce5132a1d44dab08d91f7b0eea4132b0157b303ebb8ded20a9cbd893d25402d2aeddb23fac1f428ab4947b295d6fa51dd1c334a9e76f0 - languageName: node - linkType: hard - "regjsparser@npm:^0.13.0": version: 0.13.0 resolution: "regjsparser@npm:0.13.0" @@ -12179,59 +11596,33 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.7, resolve@npm:^1.22.8": - version: 1.22.9 - resolution: "resolve@npm:1.22.9" - dependencies: - is-core-module: ^2.16.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: dd7da6c4ccc60bb4884f636b987102bb1cae6c486f7172361719a7f52769660c9a83a2d3520bef71d91f3da27e4fb8a40404c63ee4372a15863f3208bef5af67 - languageName: node - linkType: hard - -"resolve@npm:^1.22.10": +"resolve@npm:^1.22.11": version: 1.22.11 resolution: "resolve@npm:1.22.11" dependencies: - is-core-module: ^2.16.1 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: 6d5baa2156b95a65ac431e7642e21106584e9f4194da50871cae8bc1bbd2b53bb7cee573c92543d83bb999620b224a087f62379d800ed1ccb189da6df5d78d50 - languageName: node - linkType: hard - -"resolve@patch:resolve@1.22.10#~builtin": - version: 1.22.10 - resolution: "resolve@patch:resolve@npm%3A1.22.10#~builtin::version=1.22.10&hash=c3c19d" - dependencies: - is-core-module: ^2.16.0 + is-core-module: ^2.16.1 path-parse: ^1.0.7 supports-preserve-symlinks-flag: ^1.0.0 bin: resolve: bin/resolve - checksum: 8aac1e4e4628bd00bf4b94b23de137dd3fe44097a8d528fd66db74484be929936e20c696e1a3edf4488f37e14180b73df6f600992baea3e089e8674291f16c9d + checksum: 6d5baa2156b95a65ac431e7642e21106584e9f4194da50871cae8bc1bbd2b53bb7cee573c92543d83bb999620b224a087f62379d800ed1ccb189da6df5d78d50 languageName: node linkType: hard -"resolve@patch:resolve@^1.1.7#~builtin, resolve@patch:resolve@^1.22.8#~builtin": - version: 1.22.9 - resolution: "resolve@patch:resolve@npm%3A1.22.9#~builtin::version=1.22.9&hash=c3c19d" +"resolve@patch:resolve@1.22.10#~builtin": + version: 1.22.10 + resolution: "resolve@patch:resolve@npm%3A1.22.10#~builtin::version=1.22.10&hash=c3c19d" dependencies: is-core-module: ^2.16.0 path-parse: ^1.0.7 supports-preserve-symlinks-flag: ^1.0.0 bin: resolve: bin/resolve - checksum: 8db5c0f16ab65f58c036cb5be0964605c97c29b9fdf1e20f298ec027e2a4fd96ad0413aa14f6e761629956dc552cd478c2f9b6c5a07e37e4c85209090162501e + checksum: 8aac1e4e4628bd00bf4b94b23de137dd3fe44097a8d528fd66db74484be929936e20c696e1a3edf4488f37e14180b73df6f600992baea3e089e8674291f16c9d languageName: node linkType: hard -"resolve@patch:resolve@^1.22.10#~builtin": +"resolve@patch:resolve@^1.22.11#~builtin": version: 1.22.11 resolution: "resolve@patch:resolve@npm%3A1.22.11#~builtin::version=1.22.11&hash=c3c19d" dependencies: @@ -12269,9 +11660,9 @@ __metadata: linkType: hard "reusify@npm:^1.0.4": - version: 1.0.4 - resolution: "reusify@npm:1.0.4" - checksum: c3076ebcc22a6bc252cb0b9c77561795256c22b757f40c0d8110b1300723f15ec0fc8685e8d4ea6d7666f36c79ccc793b1939c748bf36f18f542744a4e379fcc + version: 1.1.0 + resolution: "reusify@npm:1.1.0" + checksum: 64cb3142ac5e9ad689aca289585cb41d22521f4571f73e9488af39f6b1bd62f0cbb3d65e2ecc768ec6494052523f473f1eb4b55c3e9014b3590c17fc6a03e22a languageName: node linkType: hard @@ -12282,17 +11673,6 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^5.0.5": - version: 5.0.10 - resolution: "rimraf@npm:5.0.10" - dependencies: - glob: ^10.3.7 - bin: - rimraf: dist/esm/bin.mjs - checksum: 50e27388dd2b3fa6677385fc1e2966e9157c89c86853b96d02e6915663a96b7ff4d590e14f6f70e90f9b554093aa5dbc05ac3012876be558c06a65437337bc05 - languageName: node - linkType: hard - "robust-predicates@npm:^3.0.2": version: 3.0.2 resolution: "robust-predicates@npm:3.0.2" @@ -12334,6 +11714,7 @@ __metadata: amplitude-js: ^8.21.9 angular-password-strength-meter: "npm:@eresearchqut/angular-password-strength-meter@^13.0.7" angulartics2: ^14.1.0 + chart.js: ^4.5.1 color-string: ^2.0.1 convert: ^5.12.0 date-fns: ^4.1.0 @@ -12347,6 +11728,7 @@ __metadata: mermaid: ^11.12.1 monaco-editor: 0.55.1 ng-dynamic-component: ^10.8.0 + ng2-charts: ^8.0.0 ngx-cookie-service: ^19.0.0 ngx-markdown: ^19.1.1 ngx-stripe: ^19.0.0 @@ -12448,34 +11830,34 @@ __metadata: linkType: hard "rollup@npm:^4.43.0": - version: 4.55.1 - resolution: "rollup@npm:4.55.1" - dependencies: - "@rollup/rollup-android-arm-eabi": 4.55.1 - "@rollup/rollup-android-arm64": 4.55.1 - "@rollup/rollup-darwin-arm64": 4.55.1 - "@rollup/rollup-darwin-x64": 4.55.1 - "@rollup/rollup-freebsd-arm64": 4.55.1 - "@rollup/rollup-freebsd-x64": 4.55.1 - "@rollup/rollup-linux-arm-gnueabihf": 4.55.1 - "@rollup/rollup-linux-arm-musleabihf": 4.55.1 - "@rollup/rollup-linux-arm64-gnu": 4.55.1 - "@rollup/rollup-linux-arm64-musl": 4.55.1 - "@rollup/rollup-linux-loong64-gnu": 4.55.1 - "@rollup/rollup-linux-loong64-musl": 4.55.1 - "@rollup/rollup-linux-ppc64-gnu": 4.55.1 - "@rollup/rollup-linux-ppc64-musl": 4.55.1 - "@rollup/rollup-linux-riscv64-gnu": 4.55.1 - "@rollup/rollup-linux-riscv64-musl": 4.55.1 - "@rollup/rollup-linux-s390x-gnu": 4.55.1 - "@rollup/rollup-linux-x64-gnu": 4.55.1 - "@rollup/rollup-linux-x64-musl": 4.55.1 - "@rollup/rollup-openbsd-x64": 4.55.1 - "@rollup/rollup-openharmony-arm64": 4.55.1 - "@rollup/rollup-win32-arm64-msvc": 4.55.1 - "@rollup/rollup-win32-ia32-msvc": 4.55.1 - "@rollup/rollup-win32-x64-gnu": 4.55.1 - "@rollup/rollup-win32-x64-msvc": 4.55.1 + version: 4.57.1 + resolution: "rollup@npm:4.57.1" + dependencies: + "@rollup/rollup-android-arm-eabi": 4.57.1 + "@rollup/rollup-android-arm64": 4.57.1 + "@rollup/rollup-darwin-arm64": 4.57.1 + "@rollup/rollup-darwin-x64": 4.57.1 + "@rollup/rollup-freebsd-arm64": 4.57.1 + "@rollup/rollup-freebsd-x64": 4.57.1 + "@rollup/rollup-linux-arm-gnueabihf": 4.57.1 + "@rollup/rollup-linux-arm-musleabihf": 4.57.1 + "@rollup/rollup-linux-arm64-gnu": 4.57.1 + "@rollup/rollup-linux-arm64-musl": 4.57.1 + "@rollup/rollup-linux-loong64-gnu": 4.57.1 + "@rollup/rollup-linux-loong64-musl": 4.57.1 + "@rollup/rollup-linux-ppc64-gnu": 4.57.1 + "@rollup/rollup-linux-ppc64-musl": 4.57.1 + "@rollup/rollup-linux-riscv64-gnu": 4.57.1 + "@rollup/rollup-linux-riscv64-musl": 4.57.1 + "@rollup/rollup-linux-s390x-gnu": 4.57.1 + "@rollup/rollup-linux-x64-gnu": 4.57.1 + "@rollup/rollup-linux-x64-musl": 4.57.1 + "@rollup/rollup-openbsd-x64": 4.57.1 + "@rollup/rollup-openharmony-arm64": 4.57.1 + "@rollup/rollup-win32-arm64-msvc": 4.57.1 + "@rollup/rollup-win32-ia32-msvc": 4.57.1 + "@rollup/rollup-win32-x64-gnu": 4.57.1 + "@rollup/rollup-win32-x64-msvc": 4.57.1 "@types/estree": 1.0.8 fsevents: ~2.3.2 dependenciesMeta: @@ -12533,7 +11915,7 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: fd5374cd7e6046404d59d64e1346821fee0900bc9cac021078bfdd342fc54305defba882fb53e6543b5c17ce4573b30fb45ee28b9a4122548358004efdc550d2 + checksum: 687947da3f450120478aaf697f03e5a7e0a98075de3fc3c04e4d849155c44631e79e646f9f7d7c8bd11e346a95f20c7f9683e2c1cc8011496a248aa9c955a817 languageName: node linkType: hard @@ -12563,9 +11945,9 @@ __metadata: linkType: hard "run-applescript@npm:^7.0.0": - version: 7.0.0 - resolution: "run-applescript@npm:7.0.0" - checksum: b02462454d8b182ad4117e5d4626e9e6782eb2072925c9fac582170b0627ae3c1ea92ee9b2df7daf84b5e9ffe14eb1cf5fb70bc44b15c8a0bfcdb47987e2410c + version: 7.1.0 + resolution: "run-applescript@npm:7.1.0" + checksum: 8659fb5f2717b2b37a68cbfe5f678254cf24b5a82a6df3372b180c80c7c137dcd757a4166c3887e459f59a090ca414e8ea7ca97cf3ee5123db54b3b4006d7b7a languageName: node linkType: hard @@ -12585,7 +11967,7 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:7.8.2": +"rxjs@npm:7.8.2, rxjs@npm:^7.4.0": version: 7.8.2 resolution: "rxjs@npm:7.8.2" dependencies: @@ -12594,15 +11976,6 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:^7.4.0": - version: 7.8.1 - resolution: "rxjs@npm:7.8.1" - dependencies: - tslib: ^2.1.0 - checksum: de4b53db1063e618ec2eca0f7965d9137cabe98cf6be9272efe6c86b47c17b987383df8574861bcced18ebd590764125a901d5506082be84a8b8e364bf05f119 - languageName: node - linkType: hard - "safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" @@ -12668,9 +12041,9 @@ __metadata: linkType: hard "sax@npm:^1.2.4": - version: 1.4.1 - resolution: "sax@npm:1.4.1" - checksum: 3ad64df16b743f0f2eb7c38ced9692a6d924f1cd07bbe45c39576c2cf50de8290d9d04e7b2228f924c7d05fecc4ec5cf651423278e0c7b63d260c387ef3af84a + version: 1.4.4 + resolution: "sax@npm:1.4.4" + checksum: a6082a153b4ab00968894b3751f6fdc431b0b7edc2d086da67ee162a06716f4bc7d0546e875993e950c757039c9e3838747ab77f50578a6ce579f970a6feadaf languageName: node linkType: hard @@ -12683,19 +12056,7 @@ __metadata: languageName: node linkType: hard -"schema-utils@npm:^4.0.0, schema-utils@npm:^4.2.0, schema-utils@npm:^4.3.0": - version: 4.3.0 - resolution: "schema-utils@npm:4.3.0" - dependencies: - "@types/json-schema": ^7.0.9 - ajv: ^8.9.0 - ajv-formats: ^2.1.1 - ajv-keywords: ^5.1.0 - checksum: 3dbd9056727c871818eaf3cabeeb5c9e173ae2b17bbf2a9c7a2e49c220fa1a580e44df651c876aea3b4926cecf080730a39e28202cb63f2b68d99872b49cd37a - languageName: node - linkType: hard - -"schema-utils@npm:^4.3.2": +"schema-utils@npm:^4.0.0, schema-utils@npm:^4.2.0, schema-utils@npm:^4.3.0, schema-utils@npm:^4.3.3": version: 4.3.3 resolution: "schema-utils@npm:4.3.3" dependencies: @@ -12758,16 +12119,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4": - version: 7.6.3 - resolution: "semver@npm:7.6.3" - bin: - semver: bin/semver.js - checksum: 4110ec5d015c9438f322257b1c51fe30276e5f766a3f64c09edd1d7ea7118ecbc3f379f3b69032bacf13116dc7abc4ad8ce0d7e2bd642e26b0d271b56b61a7d8 - languageName: node - linkType: hard - -"semver@npm:^7.7.3": +"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.7.3": version: 7.7.3 resolution: "semver@npm:7.7.3" bin: @@ -12776,27 +12128,6 @@ __metadata: languageName: node linkType: hard -"send@npm:0.19.0": - version: 0.19.0 - resolution: "send@npm:0.19.0" - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: ~1.0.2 - escape-html: ~1.0.3 - etag: ~1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: ~1.2.1 - statuses: 2.0.1 - checksum: 5ae11bd900c1c2575525e2aa622e856804e2f96a09281ec1e39610d089f53aa69e13fd8db84b52f001d0318cf4bb0b3b904ad532fc4c0014eb90d32db0cff55f - languageName: node - linkType: hard - "send@npm:^1.1.0, send@npm:^1.2.0": version: 1.2.1 resolution: "send@npm:1.2.1" @@ -12816,6 +12147,27 @@ __metadata: languageName: node linkType: hard +"send@npm:~0.19.0, send@npm:~0.19.1": + version: 0.19.2 + resolution: "send@npm:0.19.2" + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: ~2.0.0 + escape-html: ~1.0.3 + etag: ~1.8.1 + fresh: ~0.5.2 + http-errors: ~2.0.1 + mime: 1.6.0 + ms: 2.1.3 + on-finished: ~2.4.1 + range-parser: ~1.2.1 + statuses: ~2.0.2 + checksum: f9e11b718b48dbea72daa6a80e36e5a00fb6d01b1a6cfda8b3135c9ca9db84257738283da23371f437148ccd8f400e6171cd2a3642fb43fda462da407d9d30c0 + languageName: node + linkType: hard + "serialize-javascript@npm:^6.0.2": version: 6.0.2 resolution: "serialize-javascript@npm:6.0.2" @@ -12826,29 +12178,17 @@ __metadata: linkType: hard "serve-index@npm:^1.9.1": - version: 1.9.1 - resolution: "serve-index@npm:1.9.1" + version: 1.9.2 + resolution: "serve-index@npm:1.9.2" dependencies: - accepts: ~1.3.4 + accepts: ~1.3.8 batch: 0.6.1 debug: 2.6.9 escape-html: ~1.0.3 - http-errors: ~1.6.2 - mime-types: ~2.1.17 - parseurl: ~1.3.2 - checksum: e2647ce13379485b98a53ba2ea3fbad4d44b57540d00663b02b976e426e6194d62ac465c0d862cb7057f65e0de8ab8a684aa095427a4b8612412eca0d300d22f - languageName: node - linkType: hard - -"serve-static@npm:1.16.2": - version: 1.16.2 - resolution: "serve-static@npm:1.16.2" - dependencies: - encodeurl: ~2.0.0 - escape-html: ~1.0.3 + http-errors: ~1.8.0 + mime-types: ~2.1.35 parseurl: ~1.3.3 - send: 0.19.0 - checksum: dffc52feb4cc5c68e66d0c7f3c1824d4e989f71050aefc9bd5f822a42c54c9b814f595fc5f2b717f4c7cc05396145f3e90422af31186a93f76cf15f707019759 + checksum: c9a35836f85396fc0700aaf67a7f4be99a94c4908749d5cb98e4cae67333a59530effe037344600f351154fbee3b42d8eef5182041fdc98983f2549e3c5fa97b languageName: node linkType: hard @@ -12864,10 +12204,15 @@ __metadata: languageName: node linkType: hard -"setprototypeof@npm:1.1.0": - version: 1.1.0 - resolution: "setprototypeof@npm:1.1.0" - checksum: 27cb44304d6c9e1a23bc6c706af4acaae1a7aa1054d4ec13c05f01a99fd4887109a83a8042b67ad90dbfcd100d43efc171ee036eb080667172079213242ca36e +"serve-static@npm:~1.16.2": + version: 1.16.3 + resolution: "serve-static@npm:1.16.3" + dependencies: + encodeurl: ~2.0.0 + escape-html: ~1.0.3 + parseurl: ~1.3.3 + send: ~0.19.1 + checksum: ec7599540215e6676b223ea768bf7c256819180bf14f89d0b5d249a61bbb8f10b05b2a53048a153cb2cc7f3b367f1227d2fb715fe4b09d07299a9233eda1a453 languageName: node linkType: hard @@ -12903,10 +12248,10 @@ __metadata: languageName: node linkType: hard -"shell-quote@npm:^1.8.1": - version: 1.8.2 - resolution: "shell-quote@npm:1.8.2" - checksum: 1e97b62ced1c4c5135015978ebf273bed1f425a68cf84163e83fbb0f34b3ff9471e656720dab2b7cbb4ae0f58998e686d17d166c28dfb3662acd009e8bd7faed +"shell-quote@npm:^1.8.3": + version: 1.8.3 + resolution: "shell-quote@npm:1.8.3" + checksum: 550dd84e677f8915eb013d43689c80bb114860649ec5298eb978f40b8f3d4bc4ccb072b82c094eb3548dc587144bb3965a8676f0d685c1cf4c40b5dc27166242 languageName: node linkType: hard @@ -12945,7 +12290,7 @@ __metadata: languageName: node linkType: hard -"side-channel@npm:^1.0.6, side-channel@npm:^1.1.0": +"side-channel@npm:^1.1.0": version: 1.1.0 resolution: "side-channel@npm:1.1.0" dependencies: @@ -12965,31 +12310,24 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.2": - version: 3.0.7 - resolution: "signal-exit@npm:3.0.7" - checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 - languageName: node - linkType: hard - -"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": +"signal-exit@npm:^4.1.0": version: 4.1.0 resolution: "signal-exit@npm:4.1.0" checksum: 64c757b498cb8629ffa5f75485340594d2f8189e9b08700e69199069c8e3070fb3e255f7ab873c05dc0b3cec412aea7402e10a5990cb6a050bd33ba062a6c549 languageName: node linkType: hard -"sigstore@npm:^3.0.0": - version: 3.0.0 - resolution: "sigstore@npm:3.0.0" +"sigstore@npm:^4.0.0": + version: 4.1.0 + resolution: "sigstore@npm:4.1.0" dependencies: - "@sigstore/bundle": ^3.0.0 - "@sigstore/core": ^2.0.0 - "@sigstore/protobuf-specs": ^0.3.2 - "@sigstore/sign": ^3.0.0 - "@sigstore/tuf": ^3.0.0 - "@sigstore/verify": ^2.0.0 - checksum: 02fae890fce0ffc8e6cd572c0b69ce73ec7266b489be4585029df4b316b63326c73e3e1b8d42e220fd23aad39102f4228818bf4f7010a165e3d5598f96769ed7 + "@sigstore/bundle": ^4.0.0 + "@sigstore/core": ^3.1.0 + "@sigstore/protobuf-specs": ^0.5.0 + "@sigstore/sign": ^4.1.0 + "@sigstore/tuf": ^4.0.1 + "@sigstore/verify": ^3.1.0 + checksum: 3a74c1efe18eaa73161c1be216fb55b54a5cd95af5604c29df1922144bcee1e7e5ddd4f2652510397ff4166bc8941c19d715dcfc2ce262ee861e3798e84a8859 languageName: node linkType: hard @@ -13015,12 +12353,12 @@ __metadata: linkType: hard "slice-ansi@npm:^7.1.0": - version: 7.1.0 - resolution: "slice-ansi@npm:7.1.0" + version: 7.1.2 + resolution: "slice-ansi@npm:7.1.2" dependencies: ansi-styles: ^6.2.1 is-fullwidth-code-point: ^5.0.0 - checksum: 10313dd3cf7a2e4b265f527b1684c7c568210b09743fd1bd74f2194715ed13ffba653dc93a5fa79e3b1711518b8990a732cb7143aa01ddafe626e99dfa6474b2 + checksum: 75f61e1285c294b18c88521a0cdb22cdcbe9b0fd5e8e26f649be804cc43122aa7751bd960a968e3ed7f5aa7f3c67ac605c939019eae916870ec288e878b6fafb languageName: node linkType: hard @@ -13061,12 +12399,12 @@ __metadata: linkType: hard "socks@npm:^2.8.3": - version: 2.8.3 - resolution: "socks@npm:2.8.3" + version: 2.8.7 + resolution: "socks@npm:2.8.7" dependencies: - ip-address: ^9.0.5 + ip-address: ^10.0.1 smart-buffer: ^4.2.0 - checksum: 7a6b7f6eedf7482b9e4597d9a20e09505824208006ea8f2c49b71657427f3c137ca2ae662089baa73e1971c62322d535d9d0cf1c9235cf6f55e315c18203eadd + checksum: 4bbe2c88cf0eeaf49f94b7f11564a99b2571bde6fd1e714ff95b38f89e1f97858c19e0ab0e6d39eb7f6a984fa67366825895383ed563fe59962a1d57a1d55318 languageName: node linkType: hard @@ -13141,9 +12479,9 @@ __metadata: linkType: hard "spdx-license-ids@npm:^3.0.0": - version: 3.0.20 - resolution: "spdx-license-ids@npm:3.0.20" - checksum: 0c57750bedbcff48f3d0e266fbbdaf0aab54217e182f669542ffe0b5a902dce69e8cdfa126a131e1ddd39a9bef4662e357b2b41315d7240b4a28c0a7e782bb40 + version: 3.0.22 + resolution: "spdx-license-ids@npm:3.0.22" + checksum: 3810ce1ddd8c67d7cfa76a0af05157090a2d93e5bb93bd85bf9735f1fd8062c5b510423a4669dc7d8c34b0892b27a924b1c6f8965f85d852aa25062cceff5e29 languageName: node linkType: hard @@ -13181,19 +12519,12 @@ __metadata: languageName: node linkType: hard -"sprintf-js@npm:^1.1.3": - version: 1.1.3 - resolution: "sprintf-js@npm:1.1.3" - checksum: a3fdac7b49643875b70864a9d9b469d87a40dfeaf5d34d9d0c5b1cda5fd7d065531fcb43c76357d62254c57184a7b151954156563a4d6a747015cfb41021cad0 - languageName: node - linkType: hard - -"ssri@npm:^12.0.0": - version: 12.0.0 - resolution: "ssri@npm:12.0.0" +"ssri@npm:^13.0.0": + version: 13.0.0 + resolution: "ssri@npm:13.0.0" dependencies: minipass: ^7.0.3 - checksum: ef4b6b0ae47b4a69896f5f1c4375f953b9435388c053c36d27998bc3d73e046969ccde61ab659e679142971a0b08e50478a1228f62edb994105b280f17900c98 + checksum: 9705dff9e686b11f3035fb4c3d44ce690359a15a54adcd6a18951f2763f670877321178dc72c37a2b804dba3287ecaa48726dbd0cff79b2715b1cc24521b3af3 languageName: node linkType: hard @@ -13204,21 +12535,14 @@ __metadata: languageName: node linkType: hard -"statuses@npm:2.0.1": - version: 2.0.1 - resolution: "statuses@npm:2.0.1" - checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb - languageName: node - linkType: hard - -"statuses@npm:>= 1.4.0 < 2": +"statuses@npm:>= 1.5.0 < 2": version: 1.5.0 resolution: "statuses@npm:1.5.0" checksum: c469b9519de16a4bb19600205cffb39ee471a5f17b82589757ca7bd40a8d92ebb6ed9f98b5a540c5d302ccbc78f15dc03cc0280dd6e00df1335568a5d5758a5c languageName: node linkType: hard -"statuses@npm:^2.0.1, statuses@npm:^2.0.2, statuses@npm:~2.0.2": +"statuses@npm:^2.0.1, statuses@npm:^2.0.2, statuses@npm:~2.0.1, statuses@npm:~2.0.2": version: 2.0.2 resolution: "statuses@npm:2.0.2" checksum: 6927feb50c2a75b2a4caab2c565491f7a93ad3d8dbad7b1398d52359e9243a20e2ebe35e33726dee945125ef7a515e9097d8a1b910ba2bbd818265a2f6c39879 @@ -13240,21 +12564,17 @@ __metadata: linkType: hard "streamx@npm:^2.15.0, streamx@npm:^2.21.0": - version: 2.21.1 - resolution: "streamx@npm:2.21.1" + version: 2.23.0 + resolution: "streamx@npm:2.23.0" dependencies: - bare-events: ^2.2.0 + events-universal: ^1.0.0 fast-fifo: ^1.3.2 - queue-tick: ^1.0.1 text-decoder: ^1.1.0 - dependenciesMeta: - bare-events: - optional: true - checksum: 98abdd0a926b172be6f2b306cdda3d8689a4da51e478518aa187d321ceca31ebfcbfff222c55ef4140fdc2a5c14da5db9da19fdfd7a08bcdcb0c1c6e6df96f22 + checksum: d57de47db76ffd926842afab562fc8b139d7333269c6db11da5a233e8524cd326161b48bdddd28cefc010cec0b143af04dbb6f5e92d5034839ce7428928dfcae languageName: node linkType: hard -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": +"string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": version: 4.2.3 resolution: "string-width@npm:4.2.3" dependencies: @@ -13265,17 +12585,6 @@ __metadata: languageName: node linkType: hard -"string-width@npm:^5.0.1, string-width@npm:^5.1.2": - version: 5.1.2 - resolution: "string-width@npm:5.1.2" - dependencies: - eastasianwidth: ^0.2.0 - emoji-regex: ^9.2.2 - strip-ansi: ^7.0.1 - checksum: 7369deaa29f21dda9a438686154b62c2c5f661f8dda60449088f9f980196f7908fc39fdd1803e3e01541970287cf5deae336798337e9319a7055af89dafa7193 - languageName: node - linkType: hard - "string-width@npm:^7.0.0, string-width@npm:^7.2.0": version: 7.2.0 resolution: "string-width@npm:7.2.0" @@ -13305,7 +12614,7 @@ __metadata: languageName: node linkType: hard -"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": +"strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": version: 6.0.1 resolution: "strip-ansi@npm:6.0.1" dependencies: @@ -13314,12 +12623,12 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" +"strip-ansi@npm:^7.1.0": + version: 7.1.2 + resolution: "strip-ansi@npm:7.1.2" dependencies: ansi-regex: ^6.0.1 - checksum: 859c73fcf27869c22a4e4d8c6acfe690064659e84bef9458aa6d13719d09ca88dcfd40cbf31fd0be63518ea1a643fe070b4827d353e09533a5b0b9fd4553d64d + checksum: db0e3f9654e519c8a33c50fc9304d07df5649388e7da06d3aabf66d29e5ad65d5e6315d8519d409c15b32fa82c1df7e11ed6f8cd50b0e4404463f0c9d77c8d0b languageName: node linkType: hard @@ -13346,24 +12655,6 @@ __metadata: languageName: node linkType: hard -"sucrase@npm:^3.35.0": - version: 3.35.0 - resolution: "sucrase@npm:3.35.0" - dependencies: - "@jridgewell/gen-mapping": ^0.3.2 - commander: ^4.0.0 - glob: ^10.3.10 - lines-and-columns: ^1.1.6 - mz: ^2.7.0 - pirates: ^4.0.1 - ts-interface-checker: ^0.1.9 - bin: - sucrase: bin/sucrase - sucrase-node: bin/sucrase-node - checksum: 9fc5792a9ab8a14dcf9c47dcb704431d35c1cdff1d17d55d382a31c2e8e3063870ad32ce120a80915498486246d612e30cda44f1624d9d9a10423e1a43487ad1 - languageName: node - linkType: hard - "supports-color@npm:^8.0.0": version: 8.1.1 resolution: "supports-color@npm:8.1.1" @@ -13388,42 +12679,16 @@ __metadata: linkType: hard "tailwindcss@npm:>1.0.0": - version: 3.4.16 - resolution: "tailwindcss@npm:3.4.16" - dependencies: - "@alloc/quick-lru": ^5.2.0 - arg: ^5.0.2 - chokidar: ^3.6.0 - didyoumean: ^1.2.2 - dlv: ^1.1.3 - fast-glob: ^3.3.2 - glob-parent: ^6.0.2 - is-glob: ^4.0.3 - jiti: ^1.21.6 - lilconfig: ^3.1.3 - micromatch: ^4.0.8 - normalize-path: ^3.0.0 - object-hash: ^3.0.0 - picocolors: ^1.1.1 - postcss: ^8.4.47 - postcss-import: ^15.1.0 - postcss-js: ^4.0.1 - postcss-load-config: ^4.0.2 - postcss-nested: ^6.2.0 - postcss-selector-parser: ^6.1.2 - resolve: ^1.22.8 - sucrase: ^3.35.0 - bin: - tailwind: lib/cli.js - tailwindcss: lib/cli.js - checksum: a6ec1ce07da6ea4d40a62d9b3babfc5e56da75c5efb3c6fe48317dbda6877949f011c67b4fd03cb9a680d3bd734f45dbc977ee9138f8ce59619c7c712fb1350f + version: 4.1.18 + resolution: "tailwindcss@npm:4.1.18" + checksum: 6e1ccc22d444177773f28080fd6f9430f39be31a93708c6d698859431a677eb5c1a7993996a03d8fcbc4c68b7c3fcbf724e02be108a63b92cadd731ef27daf6f languageName: node linkType: hard -"tapable@npm:^2.1.1, tapable@npm:^2.2.0, tapable@npm:^2.2.1": - version: 2.2.1 - resolution: "tapable@npm:2.2.1" - checksum: 3b7a1b4d86fa940aad46d9e73d1e8739335efd4c48322cb37d073eb6f80f5281889bf0320c6d8ffcfa1a0dd5bfdbd0f9d037e252ef972aca595330538aac4d51 +"tapable@npm:^2.2.0, tapable@npm:^2.2.1, tapable@npm:^2.3.0": + version: 2.3.0 + resolution: "tapable@npm:2.3.0" + checksum: ada1194219ad550e3626d15019d87a2b8e77521d8463ab1135f46356e987a4c37eff1e87ffdd5acd573590962e519cc81e8ea6f7ed632c66bb58c0f12bd772a4 languageName: node linkType: hard @@ -13455,37 +12720,22 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.1.11": - version: 6.2.1 - resolution: "tar@npm:6.2.1" - dependencies: - chownr: ^2.0.0 - fs-minipass: ^2.0.0 - minipass: ^5.0.0 - minizlib: ^2.1.1 - mkdirp: ^1.0.3 - yallist: ^4.0.0 - checksum: f1322768c9741a25356c11373bce918483f40fa9a25c69c59410c8a1247632487edef5fe76c5f12ac51a6356d2f1829e96d2bc34098668a2fc34d76050ac2b6c - languageName: node - linkType: hard - -"tar@npm:^7.4.3": - version: 7.4.3 - resolution: "tar@npm:7.4.3" +"tar@npm:^7.4.3, tar@npm:^7.5.4": + version: 7.5.7 + resolution: "tar@npm:7.5.7" dependencies: "@isaacs/fs-minipass": ^4.0.0 chownr: ^3.0.0 minipass: ^7.1.2 - minizlib: ^3.0.1 - mkdirp: ^3.0.1 + minizlib: ^3.1.0 yallist: ^5.0.0 - checksum: 8485350c0688331c94493031f417df069b778aadb25598abdad51862e007c39d1dd5310702c7be4a6784731a174799d8885d2fde0484269aea205b724d7b2ffa + checksum: 82fa04804b6cae4c0b46b84e97a08c39e1c17bb959350baa32d139bcf5e1fc7ebc3ceb72465dd3e2e311992386ecc13599a257d5672158490ceb9464146d5573 languageName: node linkType: hard -"terser-webpack-plugin@npm:^5.3.11": - version: 5.3.14 - resolution: "terser-webpack-plugin@npm:5.3.14" +"terser-webpack-plugin@npm:^5.3.16": + version: 5.3.16 + resolution: "terser-webpack-plugin@npm:5.3.16" dependencies: "@jridgewell/trace-mapping": ^0.3.25 jest-worker: ^27.4.5 @@ -13501,7 +12751,7 @@ __metadata: optional: true uglify-js: optional: true - checksum: 13a1e67f1675a473b18d25cb0ce65c3f0a19b5e9a93213a99ea61dc4ca996ea93aa17a221965b526f5788d242836a8249ad00538fbb322e25cb69076eb55feab + checksum: 4a9ba15a0917fa0de565f6d722cac1c5291fbb517a9afe3a2cce7edf851f0e02ee44ea45e2547aeb4fb7d599df3f1ccb04ba405879839d5425481c7180655679 languageName: node linkType: hard @@ -13520,16 +12770,16 @@ __metadata: linkType: hard "terser@npm:^5.31.1": - version: 5.37.0 - resolution: "terser@npm:5.37.0" + version: 5.46.0 + resolution: "terser@npm:5.46.0" dependencies: "@jridgewell/source-map": ^0.3.3 - acorn: ^8.8.2 + acorn: ^8.15.0 commander: ^2.20.0 source-map-support: ~0.5.20 bin: terser: bin/terser - checksum: 70c06a8ce1288ff4370a7e481beb6fc8b22fc4995371479f49df1552aa9cf8e794ace66e1da6e87057eda1745644311213f5043bda9a06cf55421eff68b3ac06 + checksum: 39d28f3723e84e80ddb4576a441adb12a6d365258fb9262e25f8b6d1e4514954e81f711008ee2ad9927f00b860a5bcbd4c1db7a6873d0f712bdcc667fb7b7557 languageName: node linkType: hard @@ -13542,30 +12792,12 @@ __metadata: languageName: node linkType: hard -"thenify-all@npm:^1.0.0": - version: 1.6.0 - resolution: "thenify-all@npm:1.6.0" - dependencies: - thenify: ">= 3.1.0 < 4" - checksum: dba7cc8a23a154cdcb6acb7f51d61511c37a6b077ec5ab5da6e8b874272015937788402fd271fdfc5f187f8cb0948e38d0a42dcc89d554d731652ab458f5343e - languageName: node - linkType: hard - -"thenify@npm:>= 3.1.0 < 4": - version: 3.3.1 - resolution: "thenify@npm:3.3.1" - dependencies: - any-promise: ^1.0.0 - checksum: 84e1b804bfec49f3531215f17b4a6e50fd4397b5f7c1bccc427b9c656e1ecfb13ea79d899930184f78bc2f57285c54d9a50a590c8868f4f0cef5c1d9f898b05e - languageName: node - linkType: hard - -"thingies@npm:^1.20.0": - version: 1.21.0 - resolution: "thingies@npm:1.21.0" +"thingies@npm:^2.5.0": + version: 2.5.0 + resolution: "thingies@npm:2.5.0" peerDependencies: tslib: ^2 - checksum: 283a2785e513dc892822dd0bbadaa79e873a7fc90b84798164717bf7cf837553e0b4518d8027b2307d8f6fc6caab088fa717112cd9196c6222763cc3cc1b7e79 + checksum: e73e4bc96aefc41e4f1fdd1cf65eb988c9837f3b5fcd8a472ee30d91c2f7fa9b144562d6b4c5dade6ce70bc5865caf3e869f6d2975cce064b1d81dac3ece3508 languageName: node linkType: hard @@ -13652,21 +12884,21 @@ __metadata: languageName: node linkType: hard -"tldts-core@npm:^7.0.19": - version: 7.0.19 - resolution: "tldts-core@npm:7.0.19" - checksum: 9270a3e23ab43995777c7dfe9b7b37b80c4c0bfe0930934a698c26e83430fbeed55a608dc35660f77cfdb87ed574a1eb3b89208ab2b6a3241a8ae9b2d5bde0ca +"tldts-core@npm:^7.0.21": + version: 7.0.21 + resolution: "tldts-core@npm:7.0.21" + checksum: d97dac83ed7ac8e6e1c658557cea256eff72b4fec314e42ec33dd430d5c0d703d6c90bd0850c8432be25e0888d1364fc1f0bebbc84c15dbe1730f80fa647069e languageName: node linkType: hard "tldts@npm:^7.0.5": - version: 7.0.19 - resolution: "tldts@npm:7.0.19" + version: 7.0.21 + resolution: "tldts@npm:7.0.21" dependencies: - tldts-core: ^7.0.19 + tldts-core: ^7.0.21 bin: tldts: bin/cli.js - checksum: 24454117e4c0c6011519c3c34ff404eec03691e43ca6a5902147dff592e0dff72b37909b72bee2969466682f992bf349e442198f5acf5ffd7ea9e31b9c2ff55e + checksum: 4749f0ab507d10639bc2ef369567980934720fd9df6cacfc000bd86c611e64843292809432b79b6c5ef0ad560479367d54fd8e0d7bd245d90a2b83b021660719 languageName: node linkType: hard @@ -13711,12 +12943,12 @@ __metadata: languageName: node linkType: hard -"tree-dump@npm:^1.0.1": - version: 1.0.2 - resolution: "tree-dump@npm:1.0.2" +"tree-dump@npm:^1.0.3, tree-dump@npm:^1.1.0": + version: 1.1.0 + resolution: "tree-dump@npm:1.1.0" peerDependencies: tslib: 2 - checksum: 3b0cae6cd74c208da77dac1c65e6a212f5678fe181f1dfffbe05752be188aa88e56d5d5c33f5701d1f603ffcf33403763f722c9e8e398085cde0c0994323cb8d + checksum: 5f6fcd1b81b0fa7c638ff43cfbd1b62738c318ac14b0c8e439b1bcca353afe90785c075e9262ee18e50a863eae2eaa919ecfc8f22a4d347a0ea4b02ba088c8c0 languageName: node linkType: hard @@ -13736,13 +12968,6 @@ __metadata: languageName: node linkType: hard -"ts-interface-checker@npm:^0.1.9": - version: 0.1.13 - resolution: "ts-interface-checker@npm:0.1.13" - checksum: 20c29189c2dd6067a8775e07823ddf8d59a33e2ffc47a1bd59a5cb28bb0121a2969a816d5e77eda2ed85b18171aa5d1c4005a6b88ae8499ec7cc49f78571cb5e - languageName: node - linkType: hard - "ts-node@npm:~10.9.2": version: 10.9.2 resolution: "ts-node@npm:10.9.2" @@ -13788,14 +13013,14 @@ __metadata: languageName: node linkType: hard -"tuf-js@npm:^3.0.1": - version: 3.0.1 - resolution: "tuf-js@npm:3.0.1" +"tuf-js@npm:^4.1.0": + version: 4.1.0 + resolution: "tuf-js@npm:4.1.0" dependencies: - "@tufjs/models": 3.0.1 - debug: ^4.3.6 - make-fetch-happen: ^14.0.1 - checksum: 5f7618c84ec60495b8bb2be7ae01811311c7fab591a373b6e45fc94d01b8a9e4de5c5c52125241edd4ecd9e1c0e5caddedb93a465690d3add0f7c40b2a10abbe + "@tufjs/models": 4.1.0 + debug: ^4.4.3 + make-fetch-happen: ^15.0.1 + checksum: 51fec075a1e3007803010fb01b3fa4057a353af37cbcf8deec947bf289f17b36bcc34c8bd80e478693999a956bf345a60d0675103c83fd54ef69d7ffb1ab1338 languageName: node linkType: hard @@ -13855,16 +13080,23 @@ __metadata: linkType: hard "ufo@npm:^1.6.1": - version: 1.6.1 - resolution: "ufo@npm:1.6.1" - checksum: 2c401dd45bd98ad00806e044aa8571aa2aa1762fffeae5e78c353192b257ef2c638159789f119e5d8d5e5200e34228cd1bbde871a8f7805de25daa8576fb1633 + version: 1.6.3 + resolution: "ufo@npm:1.6.3" + checksum: a23eff86bbbef0b9cc69c19c653c703b656c2328938576d3a60e05e246ef5a78d88b17c710afa146311c5b855950ccfee60ba8f6c8845e8d1ed6b5a9086ddad1 languageName: node linkType: hard -"undici-types@npm:~6.20.0": - version: 6.20.0 - resolution: "undici-types@npm:6.20.0" - checksum: b7bc50f012dc6afbcce56c9fd62d7e86b20a62ff21f12b7b5cbf1973b9578d90f22a9c7fe50e638e96905d33893bf2f9f16d98929c4673c2480de05c6c96ea8b +"undici-types@npm:~6.21.0": + version: 6.21.0 + resolution: "undici-types@npm:6.21.0" + checksum: 46331c7d6016bf85b3e8f20c159d62f5ae471aba1eb3dc52fff35a0259d58dcc7d592d4cc4f00c5f9243fa738a11cfa48bd20203040d4a9e6bc25e807fab7ab3 + languageName: node + linkType: hard + +"undici-types@npm:~7.16.0": + version: 7.16.0 + resolution: "undici-types@npm:7.16.0" + checksum: 1ef68fc6c5bad200c8b6f17de8e5bc5cfdcadc164ba8d7208cd087cfa8583d922d8316a7fd76c9a658c22b4123d3ff847429185094484fbc65377d695c905857 languageName: node linkType: hard @@ -13885,13 +13117,6 @@ __metadata: languageName: node linkType: hard -"unicode-match-property-value-ecmascript@npm:^2.1.0": - version: 2.2.0 - resolution: "unicode-match-property-value-ecmascript@npm:2.2.0" - checksum: 9e3151e1d0bc6be35c4cef105e317c04090364173e8462005b5cde08a1e7c858b6586486cfebac39dc2c6c8c9ee24afb245de6d527604866edfa454fe2a35fae - languageName: node - linkType: hard - "unicode-match-property-value-ecmascript@npm:^2.2.1": version: 2.2.1 resolution: "unicode-match-property-value-ecmascript@npm:2.2.1" @@ -13900,51 +13125,37 @@ __metadata: linkType: hard "unicode-property-aliases-ecmascript@npm:^2.0.0": - version: 2.1.0 - resolution: "unicode-property-aliases-ecmascript@npm:2.1.0" - checksum: 243524431893649b62cc674d877bd64ef292d6071dd2fd01ab4d5ad26efbc104ffcd064f93f8a06b7e4ec54c172bf03f6417921a0d8c3a9994161fe1f88f815b + version: 2.2.0 + resolution: "unicode-property-aliases-ecmascript@npm:2.2.0" + checksum: 0dd0f6e70130c59b4a841bac206758f70227b113145e4afe238161e3e8540e8eb79963e7a228cd90ad13d499e96f7ef4ee8940835404b2181ad9bf9c174818e3 languageName: node linkType: hard -"unique-filename@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-filename@npm:4.0.0" +"unique-filename@npm:^5.0.0": + version: 5.0.0 + resolution: "unique-filename@npm:5.0.0" dependencies: - unique-slug: ^5.0.0 - checksum: 6a62094fcac286b9ec39edbd1f8f64ff92383baa430af303dfed1ffda5e47a08a6b316408554abfddd9730c78b6106bef4ca4d02c1231a735ddd56ced77573df + unique-slug: ^6.0.0 + checksum: a5f67085caef74bdd2a6869a200ed5d68d171f5cc38435a836b5fd12cce4e4eb55e6a190298035c325053a5687ed7a3c96f0a91e82215fd14729769d9ac57d9b languageName: node linkType: hard -"unique-slug@npm:^5.0.0": - version: 5.0.0 - resolution: "unique-slug@npm:5.0.0" +"unique-slug@npm:^6.0.0": + version: 6.0.0 + resolution: "unique-slug@npm:6.0.0" dependencies: imurmurhash: ^0.1.4 - checksum: 222d0322bc7bbf6e45c08967863212398313ef73423f4125e075f893a02405a5ffdbaaf150f7dd1e99f8861348a486dd079186d27c5f2c60e465b7dcbb1d3e5b + checksum: ad6cf238b10292d944521714d31bc9f3ca79fa80cb7a154aad183056493f98e85de669412c6bbfe527ffa9bdeff36d3dd4d5bccaf562c794f2580ab11932b691 languageName: node linkType: hard -"unpipe@npm:1.0.0, unpipe@npm:~1.0.0": +"unpipe@npm:~1.0.0": version: 1.0.0 resolution: "unpipe@npm:1.0.0" checksum: 4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2 languageName: node linkType: hard -"update-browserslist-db@npm:^1.1.1": - version: 1.1.1 - resolution: "update-browserslist-db@npm:1.1.1" - dependencies: - escalade: ^3.2.0 - picocolors: ^1.1.0 - peerDependencies: - browserslist: ">= 4.21.0" - bin: - update-browserslist-db: cli.js - checksum: 2ea11bd2562122162c3e438d83a1f9125238c0844b6d16d366e3276d0c0acac6036822dc7df65fc5a89c699cdf9f174acf439c39bedf3f9a2f3983976e4b4c3e - languageName: node - linkType: hard - "update-browserslist-db@npm:^1.2.0": version: 1.2.3 resolution: "update-browserslist-db@npm:1.2.3" @@ -14009,16 +13220,23 @@ __metadata: linkType: hard "validate-npm-package-name@npm:^6.0.0": - version: 6.0.0 - resolution: "validate-npm-package-name@npm:6.0.0" - checksum: 4d018c4fa07f95534a5fea667adc653b1ef52f08bf56aff066c28394499d0a6949c0b00edbd7077c4dc1e041da9220af7c742ced67d7d2d6a1b07d10cbe91b29 + version: 6.0.2 + resolution: "validate-npm-package-name@npm:6.0.2" + checksum: f0e022b0a7f11345a92b64121b059b720204cd64406a0d65d81526181dcb70aef551c7c6bf9ca37b91607a7c6ff4d62e1f63a86c8d9b7346d722a641a4bd8789 + languageName: node + linkType: hard + +"validate-npm-package-name@npm:^7.0.0": + version: 7.0.2 + resolution: "validate-npm-package-name@npm:7.0.2" + checksum: 2a9bdc6fd5e4284c8e02279446bfd3c38c0c01222555fd3b00b4765d9d47b217d4a200910be71b80b958f6baf40d2d32e812a8632633a2ce376a9b3b74811072 languageName: node linkType: hard "validator@npm:^13.15.20": - version: 13.15.20 - resolution: "validator@npm:13.15.20" - checksum: e8e50470acbc65206fad8ac937cc692278201bb09558176a4100b90cbc7981c475eda69f49b91aee3ae04cff474c8478f672f9c641e4e0a38a9f47371e0fdfb2 + version: 13.15.26 + resolution: "validator@npm:13.15.26" + checksum: 2f9151d5b37b1ccf370fb547559ca197e40517e9c08bbea55997d3607b573edce0b1082640912dcea1656648d51271d70df37b95a15d039a0bc0033a66f77e22 languageName: node linkType: hard @@ -14285,13 +13503,13 @@ __metadata: languageName: node linkType: hard -"watchpack@npm:^2.4.1": - version: 2.4.2 - resolution: "watchpack@npm:2.4.2" +"watchpack@npm:^2.4.4": + version: 2.5.1 + resolution: "watchpack@npm:2.5.1" dependencies: glob-to-regexp: ^0.4.1 graceful-fs: ^4.1.2 - checksum: 92d9d52ce3d16fd83ed6994d1dd66a4d146998882f4c362d37adfea9ab77748a5b4d1e0c65fa104797928b2d40f635efa8f9b925a6265428a69f1e1852ca3441 + checksum: 44a6030e923fbbe2cbc51cd7fb7abdff58bc35ba68d6c3ca46e63b46f8b3502c7253e6ada384387e946df5515d3854227a84cec49eb88a315186f5c9a67a3e79 languageName: node linkType: hard @@ -14311,10 +13529,10 @@ __metadata: languageName: node linkType: hard -"webdriver-bidi-protocol@npm:0.3.8": - version: 0.3.8 - resolution: "webdriver-bidi-protocol@npm:0.3.8" - checksum: 69a0003753c29629c79632594b0369c532df282f374621b769f25debcd0b1d4377cee61469cb62c63c60b4ef0aea8c29adc11fe9a97c3c9c6ba18d4e26714e6c +"webdriver-bidi-protocol@npm:0.4.0": + version: 0.4.0 + resolution: "webdriver-bidi-protocol@npm:0.4.0" + checksum: dbd6b53cbec1939ecfa83d7f781b53cb5a121dafe4db57cf233a47af65d6535e1cf8c0e210968d859c90614e0bc5fa8d5f88adfbf3e287ae7f110a5e7e81edec languageName: node linkType: hard @@ -14325,7 +13543,7 @@ __metadata: languageName: node linkType: hard -"webpack-dev-middleware@npm:7.4.2, webpack-dev-middleware@npm:^7.4.2": +"webpack-dev-middleware@npm:7.4.2": version: 7.4.2 resolution: "webpack-dev-middleware@npm:7.4.2" dependencies: @@ -14344,6 +13562,25 @@ __metadata: languageName: node linkType: hard +"webpack-dev-middleware@npm:^7.4.2": + version: 7.4.5 + resolution: "webpack-dev-middleware@npm:7.4.5" + dependencies: + colorette: ^2.0.10 + memfs: ^4.43.1 + mime-types: ^3.0.1 + on-finished: ^2.4.1 + range-parser: ^1.2.1 + schema-utils: ^4.0.0 + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + checksum: 54c31f757fec48822c37129ba166f21985ad61a5971655e3c3b7358d997975587687d40dc6c1194f4e54615bd0916df15e4ebc3e3b5203300a52038eaeed5c0b + languageName: node + linkType: hard + "webpack-dev-server@npm:5.2.2": version: 5.2.2 resolution: "webpack-dev-server@npm:5.2.2" @@ -14400,14 +13637,7 @@ __metadata: languageName: node linkType: hard -"webpack-sources@npm:^3.0.0": - version: 3.2.3 - resolution: "webpack-sources@npm:3.2.3" - checksum: 989e401b9fe3536529e2a99dac8c1bdc50e3a0a2c8669cbafad31271eadd994bc9405f88a3039cd2e29db5e6d9d0926ceb7a1a4e7409ece021fe79c37d9c4607 - languageName: node - linkType: hard - -"webpack-sources@npm:^3.3.3": +"webpack-sources@npm:^3.0.0, webpack-sources@npm:^3.3.3": version: 3.3.3 resolution: "webpack-sources@npm:3.3.3" checksum: 243d438ec4dfe805cca20fa66d111114b1f277b8ecfa95bb6ee0a6c7d996aee682539952028c2b203a6c170e6ef56f71ecf3e366e90bf1cb58b0ae982176b651 @@ -14429,9 +13659,9 @@ __metadata: languageName: node linkType: hard -"webpack@npm:5.101.2": - version: 5.101.2 - resolution: "webpack@npm:5.101.2" +"webpack@npm:5.104.1": + version: 5.104.1 + resolution: "webpack@npm:5.104.1" dependencies: "@types/eslint-scope": ^3.7.7 "@types/estree": ^1.0.8 @@ -14441,29 +13671,29 @@ __metadata: "@webassemblyjs/wasm-parser": ^1.14.1 acorn: ^8.15.0 acorn-import-phases: ^1.0.3 - browserslist: ^4.24.0 + browserslist: ^4.28.1 chrome-trace-event: ^1.0.2 - enhanced-resolve: ^5.17.3 - es-module-lexer: ^1.2.1 + enhanced-resolve: ^5.17.4 + es-module-lexer: ^2.0.0 eslint-scope: 5.1.1 events: ^3.2.0 glob-to-regexp: ^0.4.1 graceful-fs: ^4.2.11 json-parse-even-better-errors: ^2.3.1 - loader-runner: ^4.2.0 + loader-runner: ^4.3.1 mime-types: ^2.1.27 neo-async: ^2.6.2 - schema-utils: ^4.3.2 - tapable: ^2.1.1 - terser-webpack-plugin: ^5.3.11 - watchpack: ^2.4.1 + schema-utils: ^4.3.3 + tapable: ^2.3.0 + terser-webpack-plugin: ^5.3.16 + watchpack: ^2.4.4 webpack-sources: ^3.3.3 peerDependenciesMeta: webpack-cli: optional: true bin: webpack: bin/webpack.js - checksum: bde8ab5ca339390e5c99929a69d2b2c0297593592f53497eed7f191208f4c3bea1dc3fbd3c9d9c622349ecff86a653c64423c77874d5a4b801e49e7b1d930001 + checksum: 4d187c246da5c03215a9a583682d1b8972fa0c5a446ba479d63507fe2d844dacf88a46ff7f3133dba22f07f1482f866b14e84c509c0f371ae7ad9316cad83fcb languageName: node linkType: hard @@ -14492,7 +13722,14 @@ __metadata: languageName: node linkType: hard -"whatwg-url@npm:^15.0.0, whatwg-url@npm:^15.1.0": +"whatwg-mimetype@npm:^5.0.0": + version: 5.0.0 + resolution: "whatwg-mimetype@npm:5.0.0" + checksum: 33380b6faefa17476a122a8584155b4af211574a45204988978fea53a871ce1a8882a2fc08f6a1d045948dc8aab18ea62c77d4538edda54eaefb7e9dd4a144a1 + languageName: node + linkType: hard + +"whatwg-url@npm:^15.1.0": version: 15.1.0 resolution: "whatwg-url@npm:15.1.0" dependencies: @@ -14513,14 +13750,14 @@ __metadata: languageName: node linkType: hard -"which@npm:^5.0.0": - version: 5.0.0 - resolution: "which@npm:5.0.0" +"which@npm:^6.0.0": + version: 6.0.0 + resolution: "which@npm:6.0.0" dependencies: isexe: ^3.1.1 bin: node-which: bin/which.js - checksum: 6ec99e89ba32c7e748b8a3144e64bfc74aa63e2b2eacbb61a0060ad0b961eb1a632b08fb1de067ed59b002cec3e21de18299216ebf2325ef0f78e0f121e14e90 + checksum: df19b2cd8aac94b333fa29b42e8e371a21e634a742a3b156716f7752a5afe1d73fb5d8bce9b89326f453d96879e8fe626eb421e0117eb1a3ce9fd8c97f6b7db9 languageName: node linkType: hard @@ -14543,32 +13780,6 @@ __metadata: languageName: node linkType: hard -"wireit@npm:0.14.12": - version: 0.14.12 - resolution: "wireit@npm:0.14.12" - dependencies: - brace-expansion: ^4.0.0 - chokidar: ^3.5.3 - fast-glob: ^3.2.11 - jsonc-parser: ^3.0.0 - proper-lockfile: ^4.1.2 - bin: - wireit: bin/wireit.js - checksum: 62d3a6fc0e365268bb45cb5aeb7fed5ce5994b19a65955777d2b9a8334379a7195005e6d35ed9689ebc62690c22fe3aefd94ed0ba9cf8c26ec8b948a0e3ebb67 - languageName: node - linkType: hard - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: ^4.0.0 - string-width: ^4.1.0 - strip-ansi: ^6.0.0 - checksum: a790b846fd4505de962ba728a21aaeda189b8ee1c7568ca5e817d85930e06ef8d1689d49dbf0e881e8ef84436af3a88bc49115c2e2788d841ff1b8b5b51a608b - languageName: node - linkType: hard - "wrap-ansi@npm:^6.2.0": version: 6.2.0 resolution: "wrap-ansi@npm:6.2.0" @@ -14580,25 +13791,25 @@ __metadata: languageName: node linkType: hard -"wrap-ansi@npm:^8.1.0": - version: 8.1.0 - resolution: "wrap-ansi@npm:8.1.0" +"wrap-ansi@npm:^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" dependencies: - ansi-styles: ^6.1.0 - string-width: ^5.0.1 - strip-ansi: ^7.0.1 - checksum: 371733296dc2d616900ce15a0049dca0ef67597d6394c57347ba334393599e800bab03c41d4d45221b6bc967b8c453ec3ae4749eff3894202d16800fdfe0e238 + ansi-styles: ^4.0.0 + string-width: ^4.1.0 + strip-ansi: ^6.0.0 + checksum: a790b846fd4505de962ba728a21aaeda189b8ee1c7568ca5e817d85930e06ef8d1689d49dbf0e881e8ef84436af3a88bc49115c2e2788d841ff1b8b5b51a608b languageName: node linkType: hard "wrap-ansi@npm:^9.0.0": - version: 9.0.0 - resolution: "wrap-ansi@npm:9.0.0" + version: 9.0.2 + resolution: "wrap-ansi@npm:9.0.2" dependencies: ansi-styles: ^6.2.1 string-width: ^7.0.0 strip-ansi: ^7.1.0 - checksum: b2d43b76b3d8dcbdd64768165e548aad3e54e1cae4ecd31bac9966faaa7cf0b0345677ad6879db10ba58eb446ba8fa44fb82b4951872fd397f096712467a809f + checksum: 9827bf8bbb341d2d15f26d8507d98ca2695279359073422fe089d374b30e233d24ab95beca55cf9ab8dcb89face00e919be4158af50d4b6d8eab5ef4ee399e0c languageName: node linkType: hard @@ -14609,22 +13820,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.18.0": - version: 8.18.0 - resolution: "ws@npm:8.18.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 91d4d35bc99ff6df483bdf029b9ea4bfd7af1f16fc91231a96777a63d263e1eabf486e13a2353970efc534f9faa43bdbf9ee76525af22f4752cbc5ebda333975 - languageName: node - linkType: hard - -"ws@npm:^8.18.2": +"ws@npm:^8.18.0, ws@npm:^8.18.2, ws@npm:^8.18.3, ws@npm:^8.19.0": version: 8.19.0 resolution: "ws@npm:8.19.0" peerDependencies: @@ -14639,21 +13835,6 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.18.3": - version: 8.18.3 - resolution: "ws@npm:8.18.3" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: d64ef1631227bd0c5fe21b3eb3646c9c91229402fb963d12d87b49af0a1ef757277083af23a5f85742bae1e520feddfb434cb882ea59249b15673c16dc3f36e0 - languageName: node - linkType: hard - "wsl-utils@npm:^0.1.0": version: 0.1.0 resolution: "wsl-utils@npm:0.1.0" @@ -14705,15 +13886,6 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.3.4": - version: 2.6.1 - resolution: "yaml@npm:2.6.1" - bin: - yaml: bin.mjs - checksum: 5cf2627f121dcf04ccdebce8e6cbac7c9983d465c4eab314f6fbdc13cda8a07f4e8f9c2252a382b30bcabe05ee3c683647293afd52eb37cbcefbdc7b6ebde9ee - languageName: node - linkType: hard - "yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1" @@ -14812,15 +13984,15 @@ __metadata: linkType: hard "zod@npm:^3.25 || ^4.0, zod@npm:^4.1.11": - version: 4.3.5 - resolution: "zod@npm:4.3.5" - checksum: 68691183a91c67c4102db20139f3b5af288c59b4b11eb2239d712aae99dc6c1cecaeebcb0c012b44489771be05fecba21e79f65af4b3163b220239ef0af3ec49 + version: 4.3.6 + resolution: "zod@npm:4.3.6" + checksum: 19cec761b46bae4b6e7e861ea740f3f248e50a6671825afc8a5758e27b35d6f20ccde9942422fd5cf6f8b697f18bd05ef8bb33f5f2db112ab25cc628de2fae47 languageName: node linkType: hard "zone.js@npm:~0.15.0": - version: 0.15.0 - resolution: "zone.js@npm:0.15.0" - checksum: 8cb8f99c0aa18dfc684b891576d9400385da94a342128ee998accf23cbd21d5e7d9e7a76e623872eb7a300a6d388c181dde575f39d2d9bf46d0af2310024e605 + version: 0.15.1 + resolution: "zone.js@npm:0.15.1" + checksum: 573736b1a58fed460d17bfcb8f5f2a96604c1d514d52b2065950fe62b52ed569adb71f4cd976ce4ffe43c3680d7556a09e42ea31af09dfb4f2868e6ab5525c1d languageName: node linkType: hard diff --git a/shared-code/src/data-access-layer/data-access-objects/data-access-object-agent.ts b/shared-code/src/data-access-layer/data-access-objects/data-access-object-agent.ts index 2bd5c0364..46864ffe5 100644 --- a/shared-code/src/data-access-layer/data-access-objects/data-access-object-agent.ts +++ b/shared-code/src/data-access-layer/data-access-objects/data-access-object-agent.ts @@ -1,25 +1,12 @@ /* eslint-disable security/detect-object-injection */ + +import { Readable, Stream } from 'node:stream'; import axios from 'axios'; -import jwt from 'jsonwebtoken'; -import { ERROR_MESSAGES } from '../../helpers/errors/error-messages.js'; -import { AutocompleteFieldsDS } from '../shared/data-structures/autocomplete-fields.ds.js'; -import { ConnectionAgentParams } from '../shared/data-structures/connections-params.ds.js'; -import { FilteringFieldsDS } from '../shared/data-structures/filtering-fields.ds.js'; -import { ForeignKeyDS } from '../shared/data-structures/foreign-key.ds.js'; -import { FoundRowsDS } from '../shared/data-structures/found-rows.ds.js'; -import { PrimaryKeyDS } from '../shared/data-structures/primary-key.ds.js'; -import { ReferencedTableNamesAndColumnsDS } from '../shared/data-structures/referenced-table-names-columns.ds.js'; -import { TableSettingsDS } from '../shared/data-structures/table-settings.ds.js'; -import { TableStructureDS } from '../shared/data-structures/table-structure.ds.js'; -import { TestConnectionResultDS } from '../shared/data-structures/test-result-connection.ds.js'; -import { ValidateTableSettingsDS } from '../shared/data-structures/validate-table-settings.ds.js'; -import { IDataAccessObjectAgent } from '../../shared/interfaces/data-access-object-agent.interface.js'; -import { DataAccessObjectCommandsEnum } from '../../shared/enums/data-access-object-commands.enum.js'; -import { LRUStorage } from '../../caching/lru-storage.js'; -import { TableDS } from '../shared/data-structures/table.ds.js'; -import { Stream, Readable } from 'node:stream'; import * as csv from 'csv'; +import jwt from 'jsonwebtoken'; import PQueue from 'p-queue'; +import { LRUStorage } from '../../caching/lru-storage.js'; +import { ERROR_MESSAGES } from '../../helpers/errors/error-messages.js'; import { formatOracleDate, isMSSQLDateOrTimeType, @@ -31,6 +18,20 @@ import { isPostgresDateStringByRegexp, } from '../../helpers/is-database-date.js'; import { ConnectionTypesEnum } from '../../shared/enums/connection-types-enum.js'; +import { DataAccessObjectCommandsEnum } from '../../shared/enums/data-access-object-commands.enum.js'; +import { IDataAccessObjectAgent } from '../../shared/interfaces/data-access-object-agent.interface.js'; +import { AutocompleteFieldsDS } from '../shared/data-structures/autocomplete-fields.ds.js'; +import { ConnectionAgentParams } from '../shared/data-structures/connections-params.ds.js'; +import { FilteringFieldsDS } from '../shared/data-structures/filtering-fields.ds.js'; +import { ForeignKeyDS } from '../shared/data-structures/foreign-key.ds.js'; +import { FoundRowsDS } from '../shared/data-structures/found-rows.ds.js'; +import { PrimaryKeyDS } from '../shared/data-structures/primary-key.ds.js'; +import { ReferencedTableNamesAndColumnsDS } from '../shared/data-structures/referenced-table-names-columns.ds.js'; +import { TableDS } from '../shared/data-structures/table.ds.js'; +import { TableSettingsDS } from '../shared/data-structures/table-settings.ds.js'; +import { TableStructureDS } from '../shared/data-structures/table-structure.ds.js'; +import { TestConnectionResultDS } from '../shared/data-structures/test-result-connection.ds.js'; +import { ValidateTableSettingsDS } from '../shared/data-structures/validate-table-settings.ds.js'; export class DataAccessObjectAgent implements IDataAccessObjectAgent { private readonly connection: ConnectionAgentParams;