feat: migration commands (#828)
* feat: migration commands * Update packages/server/src/modules/CLI/commands/TenantsMigrateRollback.command.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/server/src/modules/CLI/commands/TenantsMigrateLatest.command.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/server/src/modules/CLI/commands/TenantsList.command.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/server/src/modules/CLI/commands/SystemMigrateRollback.command.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/server/src/modules/CLI/commands/TenantsMigrateLatest.command.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
10
package.json
10
package.json
@@ -14,7 +14,15 @@
|
||||
"test:watch": "lerna run test:watch",
|
||||
"test:e2e": "lerna run test:e2e",
|
||||
"start:debug": "lerna run start:debug",
|
||||
"prepare": "husky install"
|
||||
"prepare": "husky install",
|
||||
"system:migrate:make": "lerna run cli:system:migrate:make --scope \"@bigcapital/server\"",
|
||||
"tenants:migrate:make": "lerna run cli:tenants:migrate:make --scope \"@bigcapital/server\"",
|
||||
"system:migrate:rollback": "lerna run cli:system:migrate:rollback --scope \"@bigcapital/server\"",
|
||||
"tenants:migrate:rollback": "lerna run cli:tenants:migrate:rollback --scope \"@bigcapital/server\"",
|
||||
"system:migrate:latest": "lerna run cli:system:migrate:latest --scope \"@bigcapital/server\"",
|
||||
"tenants:migrate:latest": "lerna run cli:tenants:migrate:latest --scope \"@bigcapital/server\"",
|
||||
"system:seed:latest": "lerna run cli:system:seed:latest --scope \"@bigcapital/server\"",
|
||||
"tenants:seed:latest": "lerna run cli:tenants:seed:latest --scope \"@bigcapital/server\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^17.4.2",
|
||||
|
||||
@@ -18,7 +18,17 @@
|
||||
"test:watch": "jest --watch",
|
||||
"test:cov": "jest --coverage",
|
||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||
"test:e2e": "jest --config ./test/jest-e2e.json --watchAll"
|
||||
"test:e2e": "jest --config ./test/jest-e2e.json --watchAll",
|
||||
"cli": "ts-node -r tsconfig-paths/register src/cli.ts",
|
||||
"cli:system:migrate:latest": "ts-node -r tsconfig-paths/register src/cli.ts system:migrate:latest",
|
||||
"cli:system:migrate:rollback": "ts-node -r tsconfig-paths/register src/cli.ts system:migrate:rollback",
|
||||
"cli:system:migrate:make": "ts-node -r tsconfig-paths/register src/cli.ts system:migrate:make",
|
||||
"cli:tenants:migrate:latest": "ts-node -r tsconfig-paths/register src/cli.ts tenants:migrate:latest",
|
||||
"cli:tenants:migrate:rollback": "ts-node -r tsconfig-paths/register src/cli.ts tenants:migrate:rollback",
|
||||
"cli:tenants:migrate:make": "ts-node -r tsconfig-paths/register src/cli.ts tenants:migrate:make",
|
||||
"cli:tenants:list": "ts-node -r tsconfig-paths/register src/cli.ts tenants:list",
|
||||
"cli:system:seed:latest": "ts-node -r tsconfig-paths/register src/cli.ts system:seed:latest",
|
||||
"cli:tenants:seed:latest": "ts-node -r tsconfig-paths/register src/cli.ts tenants:seed:latest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.576.0",
|
||||
@@ -84,6 +94,7 @@
|
||||
"multer-s3": "^3.0.1",
|
||||
"mysql": "^2.18.1",
|
||||
"mysql2": "^3.11.3",
|
||||
"nest-commander": "^3.20.1",
|
||||
"nestjs-cls": "^5.2.0",
|
||||
"nestjs-i18n": "^10.4.9",
|
||||
"nestjs-redis": "^1.3.3",
|
||||
|
||||
8
packages/server/src/cli.ts
Normal file
8
packages/server/src/cli.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { CommandFactory } from 'nest-commander';
|
||||
import { CLIModule } from './modules/CLI/CLI.module';
|
||||
|
||||
async function bootstrap() {
|
||||
await CommandFactory.run(CLIModule);
|
||||
}
|
||||
|
||||
bootstrap();
|
||||
@@ -1,5 +1,5 @@
|
||||
import { parseBoolean } from '@/utils/parse-boolean';
|
||||
import { registerAs } from '@nestjs/config';
|
||||
import { parseBoolean } from '@/utils/parse-boolean';
|
||||
|
||||
export default registerAs('signupConfirmation', () => ({
|
||||
enabled: parseBoolean<boolean>(process.env.SIGNUP_EMAIL_CONFIRMATION, false),
|
||||
|
||||
@@ -7,4 +7,6 @@ export default registerAs('systemDatabase', () => ({
|
||||
user: process.env.SYSTEM_DB_USER || process.env.DB_USER,
|
||||
password: process.env.SYSTEM_DB_PASSWORD || process.env.DB_PASSWORD,
|
||||
databaseName: process.env.SYSTEM_DB_NAME || process.env.DB_NAME,
|
||||
migrationDir: process.env.SYSTEM_DB_MIGRATION_DIR || './src/database/migrations',
|
||||
seedsDir: process.env.SYSTEM_DB_SEEDS_DIR || './src/database/seeds',
|
||||
}));
|
||||
|
||||
35
packages/server/src/modules/CLI/CLI.module.ts
Normal file
35
packages/server/src/modules/CLI/CLI.module.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { config } from '../../common/config';
|
||||
import { CommandRunnerModule } from 'nest-commander';
|
||||
import { SystemMigrateLatestCommand } from './commands/SystemMigrateLatest.command';
|
||||
import { SystemMigrateRollbackCommand } from './commands/SystemMigrateRollback.command';
|
||||
import { SystemMigrateMakeCommand } from './commands/SystemMigrateMake.command';
|
||||
import { TenantsMigrateLatestCommand } from './commands/TenantsMigrateLatest.command';
|
||||
import { TenantsMigrateRollbackCommand } from './commands/TenantsMigrateRollback.command';
|
||||
import { TenantsMigrateMakeCommand } from './commands/TenantsMigrateMake.command';
|
||||
import { TenantsListCommand } from './commands/TenantsList.command';
|
||||
import { SystemSeedLatestCommand } from './commands/SystemSeedLatest.command';
|
||||
import { TenantsSeedLatestCommand } from './commands/TenantsSeedLatest.command';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
load: config,
|
||||
isGlobal: true,
|
||||
}),
|
||||
CommandRunnerModule,
|
||||
],
|
||||
providers: [
|
||||
SystemMigrateLatestCommand,
|
||||
SystemMigrateRollbackCommand,
|
||||
SystemMigrateMakeCommand,
|
||||
TenantsMigrateLatestCommand,
|
||||
TenantsMigrateRollbackCommand,
|
||||
TenantsMigrateMakeCommand,
|
||||
TenantsListCommand,
|
||||
SystemSeedLatestCommand,
|
||||
TenantsSeedLatestCommand,
|
||||
],
|
||||
})
|
||||
export class CLIModule { }
|
||||
83
packages/server/src/modules/CLI/commands/BaseCommand.ts
Normal file
83
packages/server/src/modules/CLI/commands/BaseCommand.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import { CommandRunner } from 'nest-commander';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import Knex from 'knex';
|
||||
import { knexSnakeCaseMappers } from 'objection';
|
||||
|
||||
@Injectable()
|
||||
export abstract class BaseCommand extends CommandRunner {
|
||||
constructor(protected readonly configService: ConfigService) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected initSystemKnex(): any {
|
||||
return Knex({
|
||||
client: this.configService.get('systemDatabase.client'),
|
||||
connection: {
|
||||
host: this.configService.get('systemDatabase.host'),
|
||||
user: this.configService.get('systemDatabase.user'),
|
||||
password: this.configService.get('systemDatabase.password'),
|
||||
database: this.configService.get('systemDatabase.databaseName'),
|
||||
charset: 'utf8',
|
||||
},
|
||||
migrations: {
|
||||
directory: this.configService.get('systemDatabase.migrationDir'),
|
||||
},
|
||||
seeds: {
|
||||
directory: this.configService.get('systemDatabase.seedsDir'),
|
||||
},
|
||||
pool: { min: 0, max: 7 },
|
||||
...knexSnakeCaseMappers({ upperCase: true }),
|
||||
});
|
||||
}
|
||||
|
||||
protected initTenantKnex(organizationId: string = ''): any {
|
||||
return Knex({
|
||||
client: this.configService.get('tenantDatabase.client'),
|
||||
connection: {
|
||||
host: this.configService.get('tenantDatabase.host'),
|
||||
user: this.configService.get('tenantDatabase.user'),
|
||||
password: this.configService.get('tenantDatabase.password'),
|
||||
database: `${this.configService.get('tenantDatabase.dbNamePrefix')}${organizationId}`,
|
||||
charset: 'utf8',
|
||||
},
|
||||
migrations: {
|
||||
directory: this.configService.get('tenantDatabase.migrationsDir') || './src/database/migrations',
|
||||
},
|
||||
seeds: {
|
||||
directory: this.configService.get('tenantDatabase.seedsDir') || './src/database/seeds/core',
|
||||
},
|
||||
pool: {
|
||||
min: 0,
|
||||
max: 5,
|
||||
},
|
||||
...knexSnakeCaseMappers({ upperCase: true }),
|
||||
});
|
||||
}
|
||||
|
||||
protected getAllSystemTenants(knex: any) {
|
||||
return knex('tenants');
|
||||
}
|
||||
|
||||
protected getAllInitializedTenants(knex: any) {
|
||||
return knex('tenants').whereNotNull('initializedAt');
|
||||
}
|
||||
|
||||
protected exit(text: any): never {
|
||||
if (text instanceof Error) {
|
||||
console.error(`Error: ${text.message}\n${text.stack}`);
|
||||
} else {
|
||||
console.error(`Error: ${text}`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
protected success(text: string): never {
|
||||
console.log(text);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
protected log(text: string): void {
|
||||
console.log(text);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Command } from 'nest-commander';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { BaseCommand } from './BaseCommand';
|
||||
|
||||
@Injectable()
|
||||
@Command({
|
||||
name: 'system:migrate:latest',
|
||||
description: 'Migrate latest migration of the system database.',
|
||||
})
|
||||
export class SystemMigrateLatestCommand extends BaseCommand {
|
||||
constructor(configService: ConfigService) {
|
||||
super(configService);
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
try {
|
||||
const sysKnex = this.initSystemKnex();
|
||||
const [batchNo, log] = await sysKnex.migrate.latest();
|
||||
|
||||
if (log.length === 0) {
|
||||
this.success('Already up to date');
|
||||
}
|
||||
|
||||
this.success(
|
||||
`Batch ${batchNo} run: ${log.length} migrations`
|
||||
);
|
||||
} catch (error) {
|
||||
this.exit(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Command } from 'nest-commander';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { BaseCommand } from './BaseCommand';
|
||||
|
||||
@Injectable()
|
||||
@Command({
|
||||
name: 'system:migrate:make',
|
||||
description: 'Create a named migration file to the system database.',
|
||||
arguments: '<name>',
|
||||
})
|
||||
export class SystemMigrateMakeCommand extends BaseCommand {
|
||||
constructor(configService: ConfigService) {
|
||||
super(configService);
|
||||
}
|
||||
|
||||
async run(passedParams: string[]): Promise<void> {
|
||||
const [name] = passedParams;
|
||||
|
||||
if (!name) {
|
||||
this.exit('Migration name is required');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const sysKnex = this.initSystemKnex();
|
||||
const migrationName = await sysKnex.migrate.make(name);
|
||||
this.success(`Created Migration: ${migrationName}`);
|
||||
} catch (error) {
|
||||
this.exit(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Command } from 'nest-commander';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { BaseCommand } from './BaseCommand';
|
||||
|
||||
@Injectable()
|
||||
@Command({
|
||||
name: 'system:migrate:rollback',
|
||||
description: 'Rollback the last batch of system migrations.',
|
||||
})
|
||||
export class SystemMigrateRollbackCommand extends BaseCommand {
|
||||
constructor(configService: ConfigService) {
|
||||
super(configService);
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
try {
|
||||
const sysKnex = this.initSystemKnex();
|
||||
const [batchNo, _log] = await sysKnex.migrate.rollback();
|
||||
|
||||
if (_log.length === 0) {
|
||||
this.success('Already at the base migration');
|
||||
}
|
||||
|
||||
this.success(
|
||||
`Batch ${batchNo} rolled back: ${_log.length} migrations`
|
||||
);
|
||||
} catch (error) {
|
||||
this.exit(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Command, CommandRunner } from 'nest-commander';
|
||||
|
||||
@Command({
|
||||
name: 'system:seed:latest',
|
||||
description: 'Seed system database with the latest data',
|
||||
})
|
||||
export class SystemSeedLatestCommand extends CommandRunner {
|
||||
async run(): Promise<void> {
|
||||
console.log('System seeding with latest data - No operation performed');
|
||||
// TODO: Implement system seeding logic
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import { Command, Option } from 'nest-commander';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { BaseCommand } from './BaseCommand';
|
||||
|
||||
interface TenantsListOptions {
|
||||
all?: boolean;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@Command({
|
||||
name: 'tenants:list',
|
||||
description: 'Retrieve a list of all system tenants databases.',
|
||||
})
|
||||
export class TenantsListCommand extends BaseCommand {
|
||||
constructor(configService: ConfigService) {
|
||||
super(configService);
|
||||
}
|
||||
|
||||
@Option({
|
||||
flags: '-a, --all',
|
||||
description: 'All tenants even if not initialized.',
|
||||
})
|
||||
parseAll(val: string): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
async run(passedParams: string[], options: TenantsListOptions): Promise<void> {
|
||||
try {
|
||||
const sysKnex = this.initSystemKnex();
|
||||
const tenants = options.all
|
||||
? await this.getAllSystemTenants(sysKnex)
|
||||
: await this.getAllInitializedTenants(sysKnex);
|
||||
|
||||
tenants.forEach((tenant: any) => {
|
||||
const dbName = `${this.configService.get('tenantDatabase.dbNamePrefix')}${tenant.organizationId}`;
|
||||
console.log(
|
||||
`ID: ${tenant.id} | Organization ID: ${tenant.organizationId} | DB Name: ${dbName}`
|
||||
);
|
||||
});
|
||||
|
||||
this.success('---');
|
||||
} catch (error) {
|
||||
this.exit(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import { Command, Option } from 'nest-commander';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { PromisePool } from '@supercharge/promise-pool';
|
||||
import { BaseCommand } from './BaseCommand';
|
||||
|
||||
interface TenantsMigrateLatestOptions {
|
||||
tenant_id?: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@Command({
|
||||
name: 'tenants:migrate:latest',
|
||||
description: 'Migrate all tenants or the given tenant id.',
|
||||
})
|
||||
export class TenantsMigrateLatestCommand extends BaseCommand {
|
||||
private readonly MIGRATION_CONCURRENCY = 10;
|
||||
|
||||
constructor(configService: ConfigService) {
|
||||
super(configService);
|
||||
}
|
||||
|
||||
@Option({
|
||||
flags: '-t, --tenant_id [tenant_id]',
|
||||
description: 'Which organization id do you migrate.',
|
||||
})
|
||||
parseTenantId(val: string): string {
|
||||
return val;
|
||||
}
|
||||
|
||||
async run(passedParams: string[], options: TenantsMigrateLatestOptions): Promise<void> {
|
||||
try {
|
||||
const sysKnex = this.initSystemKnex();
|
||||
const tenants = await this.getAllInitializedTenants(sysKnex);
|
||||
const tenantsOrgsIds = tenants.map((tenant: any) => tenant.organizationId);
|
||||
|
||||
if (options.tenant_id && tenantsOrgsIds.indexOf(options.tenant_id) === -1) {
|
||||
this.exit(`The given tenant id ${options.tenant_id} does not exist.`);
|
||||
}
|
||||
|
||||
const migrateTenant = async (organizationId: string) => {
|
||||
try {
|
||||
const tenantKnex = this.initTenantKnex(organizationId);
|
||||
const [batchNo, _log] = await tenantKnex.migrate.latest();
|
||||
const tenantDb = `${this.configService.get('tenantDatabase.dbNamePrefix')}${organizationId}`;
|
||||
|
||||
if (_log.length === 0) {
|
||||
this.log('Already up to date');
|
||||
}
|
||||
|
||||
this.log(
|
||||
`Tenant ${tenantDb} > Batch ${batchNo} run: ${_log.length} migrations`
|
||||
);
|
||||
this.log('-------------------');
|
||||
} catch (error) {
|
||||
this.exit(error);
|
||||
}
|
||||
};
|
||||
|
||||
if (!options.tenant_id) {
|
||||
await PromisePool.withConcurrency(this.MIGRATION_CONCURRENCY)
|
||||
.for(tenants)
|
||||
.process((tenant: any) => {
|
||||
return migrateTenant(tenant.organizationId);
|
||||
});
|
||||
this.success('All tenants are migrated.');
|
||||
} else {
|
||||
await migrateTenant(options.tenant_id);
|
||||
}
|
||||
} catch (error) {
|
||||
this.exit(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Command } from 'nest-commander';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { BaseCommand } from './BaseCommand';
|
||||
|
||||
@Injectable()
|
||||
@Command({
|
||||
name: 'tenants:migrate:make',
|
||||
description: 'Create a named migration file to the tenants database.',
|
||||
arguments: '<name>',
|
||||
})
|
||||
export class TenantsMigrateMakeCommand extends BaseCommand {
|
||||
constructor(configService: ConfigService) {
|
||||
super(configService);
|
||||
}
|
||||
|
||||
async run(passedParams: string[]): Promise<void> {
|
||||
const [name] = passedParams;
|
||||
|
||||
if (!name) {
|
||||
this.exit('Migration name is required');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const tenantKnex = this.initTenantKnex();
|
||||
const migrationName = await tenantKnex.migrate.make(name);
|
||||
this.success(`Created Migration: ${migrationName}`);
|
||||
} catch (error) {
|
||||
this.exit(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import { Command, Option } from 'nest-commander';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { PromisePool } from '@supercharge/promise-pool';
|
||||
import { BaseCommand } from './BaseCommand';
|
||||
|
||||
interface TenantsMigrateRollbackOptions {
|
||||
tenant_id?: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@Command({
|
||||
name: 'tenants:migrate:rollback',
|
||||
description: 'Rollback the last batch of tenants migrations.',
|
||||
})
|
||||
export class TenantsMigrateRollbackCommand extends BaseCommand {
|
||||
private readonly MIGRATION_CONCURRENCY = 10;
|
||||
|
||||
constructor(configService: ConfigService) {
|
||||
super(configService);
|
||||
}
|
||||
|
||||
@Option({
|
||||
flags: '-t, --tenant_id [tenant_id]',
|
||||
description: 'Which organization id do you migrate.',
|
||||
})
|
||||
parseTenantId(val: string): string {
|
||||
return val;
|
||||
}
|
||||
|
||||
async run(passedParams: string[], options: TenantsMigrateRollbackOptions): Promise<void> {
|
||||
try {
|
||||
const sysKnex = this.initSystemKnex();
|
||||
const tenants = await this.getAllInitializedTenants(sysKnex);
|
||||
const tenantsOrgsIds = tenants.map((tenant: any) => tenant.organizationId);
|
||||
|
||||
if (options.tenant_id && tenantsOrgsIds.indexOf(options.tenant_id) === -1) {
|
||||
this.exit(`The given tenant id ${options.tenant_id} does not exist.`);
|
||||
}
|
||||
|
||||
const migrateTenant = async (organizationId: string) => {
|
||||
try {
|
||||
const tenantKnex = this.initTenantKnex(organizationId);
|
||||
const [batchNo, _log] = await tenantKnex.migrate.rollback();
|
||||
const tenantDb = `${this.configService.get('tenantDatabase.dbNamePrefix')}${organizationId}`;
|
||||
|
||||
if (_log.length === 0) {
|
||||
this.log('Already at the base migration');
|
||||
}
|
||||
|
||||
this.log(
|
||||
`Tenant: ${tenantDb} > Batch ${batchNo} rolled back: ${_log.length} migrations`
|
||||
);
|
||||
this.log('---------------');
|
||||
} catch (error) {
|
||||
this.exit(error);
|
||||
}
|
||||
};
|
||||
|
||||
if (!options.tenant_id) {
|
||||
await PromisePool.withConcurrency(this.MIGRATION_CONCURRENCY)
|
||||
.for(tenants)
|
||||
.process((tenant: any) => {
|
||||
return migrateTenant(tenant.organizationId);
|
||||
});
|
||||
this.success('All tenants are rollbacked.');
|
||||
} else {
|
||||
await migrateTenant(options.tenant_id);
|
||||
}
|
||||
} catch (error) {
|
||||
this.exit(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Command, CommandRunner } from 'nest-commander';
|
||||
|
||||
@Command({
|
||||
name: 'tenants:seed:latest',
|
||||
description: 'Seed all tenant databases with the latest data',
|
||||
})
|
||||
export class TenantsSeedLatestCommand extends CommandRunner {
|
||||
async run(): Promise<void> {
|
||||
console.log('Tenants seeding with latest data - No operation performed');
|
||||
// TODO: Implement tenants seeding logic
|
||||
}
|
||||
}
|
||||
127
pnpm-lock.yaml
generated
127
pnpm-lock.yaml
generated
@@ -228,6 +228,9 @@ importers:
|
||||
mysql2:
|
||||
specifier: ^3.11.3
|
||||
version: 3.11.4
|
||||
nest-commander:
|
||||
specifier: ^3.20.1
|
||||
version: 3.20.1(@nestjs/common@10.4.7)(@nestjs/core@10.4.7)(@types/inquirer@8.2.12)(@types/node@20.5.1)(typescript@5.6.3)
|
||||
nestjs-cls:
|
||||
specifier: ^5.2.0
|
||||
version: 5.2.0(@nestjs/common@10.4.7)(@nestjs/core@10.4.7)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||
@@ -5867,6 +5870,15 @@ packages:
|
||||
resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==}
|
||||
dev: true
|
||||
|
||||
/@fig/complete-commander@3.2.0(commander@11.1.0):
|
||||
resolution: {integrity: sha512-1Holl3XtRiANVKURZwgpjCnPuV4RsHp+XC0MhgvyAX/avQwj7F2HUItYOvGi/bXjJCkEzgBZmVfCr0HBA+q+Bw==}
|
||||
peerDependencies:
|
||||
commander: ^11.1.0
|
||||
dependencies:
|
||||
commander: 11.1.0
|
||||
prettier: 3.3.3
|
||||
dev: false
|
||||
|
||||
/@floating-ui/core@1.6.8:
|
||||
resolution: {integrity: sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==}
|
||||
dependencies:
|
||||
@@ -5907,6 +5919,17 @@ packages:
|
||||
deprecated: the package is rather renamed to @formatjs/ecma-abstract with some changes in functionality (primarily selectUnit is removed and we don't plan to make any further changes to this package
|
||||
dev: false
|
||||
|
||||
/@golevelup/nestjs-discovery@5.0.0(@nestjs/common@10.4.7)(@nestjs/core@10.4.7):
|
||||
resolution: {integrity: sha512-NaIWLCLI+XvneUK05LH2idHLmLNITYT88YnpOuUQmllKtiJNIS3woSt7QXrMZ5k3qUWuZpehEVz1JtlX4I1KyA==}
|
||||
peerDependencies:
|
||||
'@nestjs/common': ^11.0.20
|
||||
'@nestjs/core': ^11.0.20
|
||||
dependencies:
|
||||
'@nestjs/common': 10.4.7(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||
'@nestjs/core': 10.4.7(@nestjs/common@10.4.7)(@nestjs/platform-express@10.4.7)(@nestjs/websockets@10.4.20)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||
lodash: 4.17.21
|
||||
dev: false
|
||||
|
||||
/@humanfs/core@0.19.0:
|
||||
resolution: {integrity: sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==}
|
||||
engines: {node: '>=18.18.0'}
|
||||
@@ -5961,6 +5984,20 @@ packages:
|
||||
warning: 4.0.3
|
||||
dev: false
|
||||
|
||||
/@inquirer/external-editor@1.0.2(@types/node@20.5.1):
|
||||
resolution: {integrity: sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@types/node': '>=18'
|
||||
peerDependenciesMeta:
|
||||
'@types/node':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@types/node': 20.5.1
|
||||
chardet: 2.1.0
|
||||
iconv-lite: 0.7.0
|
||||
dev: false
|
||||
|
||||
/@ioredis/commands@1.2.0:
|
||||
resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==}
|
||||
dev: false
|
||||
@@ -11681,6 +11718,13 @@ packages:
|
||||
'@types/node': 20.5.1
|
||||
dev: false
|
||||
|
||||
/@types/inquirer@8.2.12:
|
||||
resolution: {integrity: sha512-YxURZF2ZsSjU5TAe06tW0M3sL4UI9AMPA6dd8I72uOtppzNafcY38xkYgCZ/vsVOAyNdzHmvtTpLWilOrbP0dQ==}
|
||||
dependencies:
|
||||
'@types/through': 0.0.33
|
||||
rxjs: 7.8.1
|
||||
dev: false
|
||||
|
||||
/@types/ioredis@5.0.0:
|
||||
resolution: {integrity: sha512-zJbJ3FVE17CNl5KXzdeSPtdltc4tMT3TzC6fxQS0sQngkbFZ6h+0uTafsRqu+eSLIugf6Yb0Ea0SUuRr42Nk9g==}
|
||||
deprecated: This is a stub types definition. ioredis provides its own type definitions, so you do not need this installed.
|
||||
@@ -12073,6 +12117,12 @@ packages:
|
||||
pretty-format: 25.5.0
|
||||
dev: false
|
||||
|
||||
/@types/through@0.0.33:
|
||||
resolution: {integrity: sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==}
|
||||
dependencies:
|
||||
'@types/node': 20.5.1
|
||||
dev: false
|
||||
|
||||
/@types/trusted-types@2.0.7:
|
||||
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
|
||||
dev: false
|
||||
@@ -14135,7 +14185,6 @@ packages:
|
||||
buffer: 5.7.1
|
||||
inherits: 2.0.4
|
||||
readable-stream: 3.6.2
|
||||
dev: true
|
||||
|
||||
/bluebird@3.7.2:
|
||||
resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
|
||||
@@ -14338,7 +14387,6 @@ packages:
|
||||
dependencies:
|
||||
base64-js: 1.5.1
|
||||
ieee754: 1.2.1
|
||||
dev: true
|
||||
|
||||
/buffer@6.0.3:
|
||||
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
|
||||
@@ -14679,6 +14727,10 @@ packages:
|
||||
resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
|
||||
dev: true
|
||||
|
||||
/chardet@2.1.0:
|
||||
resolution: {integrity: sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==}
|
||||
dev: false
|
||||
|
||||
/check-error@2.1.1:
|
||||
resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
|
||||
engines: {node: '>= 16'}
|
||||
@@ -14768,7 +14820,6 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
restore-cursor: 3.1.0
|
||||
dev: true
|
||||
|
||||
/cli-spinners@2.6.1:
|
||||
resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==}
|
||||
@@ -14778,7 +14829,6 @@ packages:
|
||||
/cli-spinners@2.9.2:
|
||||
resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/cli-table3@0.6.5:
|
||||
resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==}
|
||||
@@ -14792,7 +14842,6 @@ packages:
|
||||
/cli-width@3.0.0:
|
||||
resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==}
|
||||
engines: {node: '>= 10'}
|
||||
dev: true
|
||||
|
||||
/cli-width@4.1.0:
|
||||
resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==}
|
||||
@@ -14826,7 +14875,6 @@ packages:
|
||||
/clone@1.0.4:
|
||||
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
|
||||
engines: {node: '>=0.8'}
|
||||
dev: true
|
||||
|
||||
/clsx@1.2.1:
|
||||
resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==}
|
||||
@@ -14928,6 +14976,11 @@ packages:
|
||||
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
/commander@11.1.0:
|
||||
resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
|
||||
engines: {node: '>=16'}
|
||||
dev: false
|
||||
|
||||
/commander@2.20.3:
|
||||
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
||||
|
||||
@@ -15909,7 +15962,6 @@ packages:
|
||||
resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
|
||||
dependencies:
|
||||
clone: 1.0.4
|
||||
dev: true
|
||||
|
||||
/define-data-property@1.1.4:
|
||||
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
|
||||
@@ -17735,7 +17787,6 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
escape-string-regexp: 1.0.5
|
||||
dev: true
|
||||
|
||||
/file-entry-cache@6.0.1:
|
||||
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
|
||||
@@ -19136,6 +19187,13 @@ packages:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
|
||||
/iconv-lite@0.7.0:
|
||||
resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
dev: false
|
||||
|
||||
/icss-utils@5.1.0(postcss@8.4.47):
|
||||
resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==}
|
||||
engines: {node: ^10 || ^12 || >= 14}
|
||||
@@ -19287,6 +19345,29 @@ packages:
|
||||
wrap-ansi: 6.2.0
|
||||
dev: true
|
||||
|
||||
/inquirer@8.2.7(@types/node@20.5.1):
|
||||
resolution: {integrity: sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
dependencies:
|
||||
'@inquirer/external-editor': 1.0.2(@types/node@20.5.1)
|
||||
ansi-escapes: 4.3.2
|
||||
chalk: 4.1.2
|
||||
cli-cursor: 3.1.0
|
||||
cli-width: 3.0.0
|
||||
figures: 3.2.0
|
||||
lodash: 4.17.21
|
||||
mute-stream: 0.0.8
|
||||
ora: 5.4.1
|
||||
run-async: 2.4.1
|
||||
rxjs: 7.8.1
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
through: 2.3.8
|
||||
wrap-ansi: 6.2.0
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
dev: false
|
||||
|
||||
/inquirer@9.2.15:
|
||||
resolution: {integrity: sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -19581,7 +19662,6 @@ packages:
|
||||
/is-interactive@1.0.0:
|
||||
resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/is-lambda@1.0.1:
|
||||
resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==}
|
||||
@@ -19766,7 +19846,6 @@ packages:
|
||||
/is-unicode-supported@0.1.0:
|
||||
resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/is-weakmap@2.0.2:
|
||||
resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
|
||||
@@ -21695,7 +21774,6 @@ packages:
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
is-unicode-supported: 0.1.0
|
||||
dev: true
|
||||
|
||||
/long@5.2.3:
|
||||
resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==}
|
||||
@@ -22408,7 +22486,6 @@ packages:
|
||||
|
||||
/mute-stream@0.0.8:
|
||||
resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==}
|
||||
dev: true
|
||||
|
||||
/mute-stream@1.0.0:
|
||||
resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==}
|
||||
@@ -22527,6 +22604,26 @@ packages:
|
||||
/neo-async@2.6.2:
|
||||
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
|
||||
|
||||
/nest-commander@3.20.1(@nestjs/common@10.4.7)(@nestjs/core@10.4.7)(@types/inquirer@8.2.12)(@types/node@20.5.1)(typescript@5.6.3):
|
||||
resolution: {integrity: sha512-LRI7z6UlWy2vWyQR0PYnAXsaRyJvpfiuvOCmx2jk2kLXJH9+y/omPDl9NE3fq4WMaE0/AhviuUjA12eC/zDqXw==}
|
||||
peerDependencies:
|
||||
'@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
|
||||
'@nestjs/core': ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
|
||||
'@types/inquirer': ^8.1.3
|
||||
dependencies:
|
||||
'@fig/complete-commander': 3.2.0(commander@11.1.0)
|
||||
'@golevelup/nestjs-discovery': 5.0.0(@nestjs/common@10.4.7)(@nestjs/core@10.4.7)
|
||||
'@nestjs/common': 10.4.7(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||
'@nestjs/core': 10.4.7(@nestjs/common@10.4.7)(@nestjs/platform-express@10.4.7)(@nestjs/websockets@10.4.20)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||
'@types/inquirer': 8.2.12
|
||||
commander: 11.1.0
|
||||
cosmiconfig: 8.3.6(typescript@5.6.3)
|
||||
inquirer: 8.2.7(@types/node@20.5.1)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- typescript
|
||||
dev: false
|
||||
|
||||
/nestjs-cls@5.2.0(@nestjs/common@10.4.7)(@nestjs/core@10.4.7)(reflect-metadata@0.2.2)(rxjs@7.8.1):
|
||||
resolution: {integrity: sha512-xabZQ7aPHttZ5TwC4rEyYgsxm3/ArM+Dz4oJPWc5Q1p+jOp+UaDe37fKna6sIMeUmYpvZxMVtUKIhv7CfLxbOw==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -23254,7 +23351,6 @@ packages:
|
||||
log-symbols: 4.1.0
|
||||
strip-ansi: 6.0.1
|
||||
wcwidth: 1.0.1
|
||||
dev: true
|
||||
|
||||
/orderedmap@2.1.1:
|
||||
resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==}
|
||||
@@ -24697,7 +24793,6 @@ packages:
|
||||
resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/pretty-bytes@5.6.0:
|
||||
resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==}
|
||||
@@ -26698,7 +26793,6 @@ packages:
|
||||
dependencies:
|
||||
onetime: 5.1.2
|
||||
signal-exit: 3.0.7
|
||||
dev: true
|
||||
|
||||
/ret@0.1.15:
|
||||
resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==}
|
||||
@@ -26821,7 +26915,6 @@ packages:
|
||||
/run-async@2.4.1:
|
||||
resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==}
|
||||
engines: {node: '>=0.12.0'}
|
||||
dev: true
|
||||
|
||||
/run-async@3.0.0:
|
||||
resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==}
|
||||
@@ -29754,7 +29847,6 @@ packages:
|
||||
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
|
||||
dependencies:
|
||||
defaults: 1.0.4
|
||||
dev: true
|
||||
|
||||
/web-vitals@2.1.4:
|
||||
resolution: {integrity: sha512-sVWcwhU5mX6crfI5Vd2dC4qchyTqxV8URinzt25XqVh+bHEPGH4C3NPrNionCP7Obx59wrYEbNlw4Z8sjALzZg==}
|
||||
@@ -30425,7 +30517,6 @@ packages:
|
||||
ansi-styles: 4.3.0
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
dev: true
|
||||
|
||||
/wrap-ansi@7.0.0:
|
||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
||||
|
||||
Reference in New Issue
Block a user