Add healthchecks for Jellyfin and Discord

This commit is contained in:
Manuel 2022-12-27 16:48:16 +01:00 committed by GitHub
parent 80e138900c
commit 538b2451f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 272 additions and 114 deletions

View File

@ -32,6 +32,7 @@
"@nestjs/event-emitter": "^1.3.1",
"@nestjs/platform-express": "^9.0.0",
"@nestjs/schedule": "^2.1.0",
"@nestjs/terminus": "^9.1.4",
"date-fns": "^2.29.3",
"discord.js": "^14.7.1",
"joi": "^17.7.0",

View File

@ -12,6 +12,9 @@ import { JellyfinClientModule } from './clients/jellyfin/jellyfin.module';
import { CommandModule } from './commands/command.module';
import { PlaybackModule } from './playback/playback.module';
import { UpdatesModule } from './updates/updates.module';
import { HealthController } from './health/health.controller';
import { HealthModule } from './health/health.module';
import { TerminusModule } from '@nestjs/terminus';
@Module({
imports: [
@ -36,6 +39,7 @@ import { UpdatesModule } from './updates/updates.module';
JellyfinClientModule,
PlaybackModule,
UpdatesModule,
HealthModule,
],
controllers: [],
providers: [],

View File

@ -14,6 +14,7 @@ export class JellyfinService {
private api: Api;
private systemApi: SystemApi;
private userId: string;
private connected = false;
constructor(
private eventEmitter: EventEmitter2,
@ -56,11 +57,13 @@ export class JellyfinService {
this.userId = response.data.SessionInfo.UserId;
this.systemApi = getSystemApi(this.api);
this.connected = true;
await this.jellyfinPlayState.initializePlayState(this.api);
})
.catch((test) => {
this.logger.error(test);
this.connected = false;
});
}
@ -72,6 +75,7 @@ export class JellyfinService {
return;
}
this.api.logout();
this.connected = false;
}
getApi() {
@ -89,4 +93,8 @@ export class JellyfinService {
getUserId() {
return this.userId;
}
isConnected() {
return this.connected;
}
}

View File

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { HealthController } from './health.controller';
describe('HealthController', () => {
let controller: HealthController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [HealthController],
}).compile();
controller = module.get<HealthController>(HealthController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

View File

@ -0,0 +1,23 @@
import { Controller, Get, Injectable } from '@nestjs/common';
import { HealthCheck, HealthCheckService } from '@nestjs/terminus';
import { DiscordHealthIndicator } from './indicators/discord.indicator';
import { JellyfinHealthIndicator } from './indicators/jellyfin.indicator';
@Injectable()
@Controller('health')
export class HealthController {
constructor(
private readonly health: HealthCheckService,
private readonly discordIndicator: DiscordHealthIndicator,
private readonly jellyfinHealthIndicator: JellyfinHealthIndicator,
) {}
@Get()
@HealthCheck()
healthCheck() {
return this.health.check([
() => this.discordIndicator.isHealthy('discord'),
() => this.jellyfinHealthIndicator.isHealthy('jellyfin'),
]);
}
}

View File

@ -0,0 +1,14 @@
import { DiscordModule } from '@discord-nestjs/core';
import { Module } from '@nestjs/common';
import { TerminusModule } from '@nestjs/terminus';
import { JellyfinClientModule } from '../clients/jellyfin/jellyfin.module';
import { HealthController } from './health.controller';
import { DiscordHealthIndicator } from './indicators/discord.indicator';
import { JellyfinHealthIndicator } from './indicators/jellyfin.indicator';
@Module({
imports: [TerminusModule, JellyfinClientModule, DiscordModule.forFeature()],
controllers: [HealthController],
providers: [JellyfinHealthIndicator, DiscordHealthIndicator],
})
export class HealthModule {}

View File

@ -0,0 +1,20 @@
import { InjectDiscordClient } from '@discord-nestjs/core';
import { Injectable } from '@nestjs/common';
import { HealthIndicator, HealthIndicatorResult } from '@nestjs/terminus';
import { Client, Status } from 'discord.js';
@Injectable()
export class DiscordHealthIndicator extends HealthIndicator {
constructor(@InjectDiscordClient() private readonly client: Client) {
super();
}
async isHealthy(key: string): Promise<HealthIndicatorResult> {
const status = this.client.ws.status;
return this.getStatus(key, status === Status.Ready, {
wsStatus: status,
pingInMilliseconds: this.client.ws.ping,
});
}
}

View File

@ -0,0 +1,16 @@
import { Injectable } from '@nestjs/common';
import { HealthIndicator, HealthIndicatorResult } from '@nestjs/terminus';
import { JellyfinService } from '../../clients/jellyfin/jellyfin.service';
@Injectable()
export class JellyfinHealthIndicator extends HealthIndicator {
constructor(private readonly jellyfinService: JellyfinService) {
super();
}
async isHealthy(key: string): Promise<HealthIndicatorResult> {
const isConnected = this.jellyfinService.isConnected();
return this.getStatus(key, isConnected);
}
}

282
yarn.lock
View File

@ -15,13 +15,13 @@ __metadata:
languageName: node
linkType: hard
"@angular-devkit/core@npm:14.2.1":
version: 14.2.1
resolution: "@angular-devkit/core@npm:14.2.1"
"@angular-devkit/core@npm:15.0.4":
version: 15.0.4
resolution: "@angular-devkit/core@npm:15.0.4"
dependencies:
ajv: 8.11.0
ajv-formats: 2.1.1
jsonc-parser: 3.1.0
jsonc-parser: 3.2.0
rxjs: 6.6.7
source-map: 0.7.4
peerDependencies:
@ -29,67 +29,36 @@ __metadata:
peerDependenciesMeta:
chokidar:
optional: true
checksum: 67a4c57a6e51bbb7151fa57d5d27e2360dea55b125343ff79939fc7c15dc88b6d027303f98024c3bef3a994a901212ddb2f3d6fd6f6433760e1b7bb504f0648f
checksum: e2d7488cae4f11b008fdf3cc10cb6cfdec09a7ba36b31b7199308d21cae016bfaf41701c5e1003af6dbc1d02b929471f89a924fc258da7129d72cc9b945136cc
languageName: node
linkType: hard
"@angular-devkit/core@npm:14.2.2":
version: 14.2.2
resolution: "@angular-devkit/core@npm:14.2.2"
"@angular-devkit/schematics-cli@npm:15.0.4":
version: 15.0.4
resolution: "@angular-devkit/schematics-cli@npm:15.0.4"
dependencies:
ajv: 8.11.0
ajv-formats: 2.1.1
jsonc-parser: 3.1.0
rxjs: 6.6.7
source-map: 0.7.4
peerDependencies:
chokidar: ^3.5.2
peerDependenciesMeta:
chokidar:
optional: true
checksum: 63a38df8a6983eb07933cd4b05ebbdc0f7690ab88ebcb739c15931d048083d84527316d03f81aa37ae2ae601790d789fc4da7a764f11be27ab7edb79cf7528e6
languageName: node
linkType: hard
"@angular-devkit/schematics-cli@npm:14.2.2":
version: 14.2.2
resolution: "@angular-devkit/schematics-cli@npm:14.2.2"
dependencies:
"@angular-devkit/core": 14.2.2
"@angular-devkit/schematics": 14.2.2
"@angular-devkit/core": 15.0.4
"@angular-devkit/schematics": 15.0.4
ansi-colors: 4.1.3
inquirer: 8.2.4
symbol-observable: 4.0.0
yargs-parser: 21.1.1
bin:
schematics: bin/schematics.js
checksum: 024c334cc14bbdda8eb1e7ab2e93b908828a310ec8e0dcd8f97c6e25edb335073da706d5ba3558daafc564285bf5f1945cb1804a034f2cb8aa353813dce04fc4
checksum: f4e956795454d0ec54375a4d7b24b95d68f73cbb2be64883efb239e03d282276d9e8b9121d54c1f3fe559372d1d8405b07fdc62a9f7e593126396edbcc2a23aa
languageName: node
linkType: hard
"@angular-devkit/schematics@npm:14.2.1":
version: 14.2.1
resolution: "@angular-devkit/schematics@npm:14.2.1"
"@angular-devkit/schematics@npm:15.0.4":
version: 15.0.4
resolution: "@angular-devkit/schematics@npm:15.0.4"
dependencies:
"@angular-devkit/core": 14.2.1
jsonc-parser: 3.1.0
magic-string: 0.26.2
"@angular-devkit/core": 15.0.4
jsonc-parser: 3.2.0
magic-string: 0.26.7
ora: 5.4.1
rxjs: 6.6.7
checksum: 74af9c50b0953ae8a4cf8390d935b1acc28acb4f8816f771aa08cd9293ecdbd2bc07a3be619f4eb779e3ccfd4a71e367480787739ca47a5ff272f61c5f9ff28d
languageName: node
linkType: hard
"@angular-devkit/schematics@npm:14.2.2":
version: 14.2.2
resolution: "@angular-devkit/schematics@npm:14.2.2"
dependencies:
"@angular-devkit/core": 14.2.2
jsonc-parser: 3.1.0
magic-string: 0.26.2
ora: 5.4.1
rxjs: 6.6.7
checksum: 4a7cc5c51a3a3e12de6450e8e65e66799ae576ed78830e27eb0113e43009299cfa30cf052b1963945eb806a084cdaf7f5df2132822a6f92ca0e3be31d5d6ce3f
checksum: f9f574a0bb1931589f6c0ee32348faf7335d9d2b3411c4fc5768a7c64bae677d21ca2f100758f7e66f1fc8585ee5360dcc64c0115892c42ec756d5a182846dad
languageName: node
linkType: hard
@ -1010,18 +979,18 @@ __metadata:
linkType: hard
"@nestjs/cli@npm:^9.0.0":
version: 9.1.5
resolution: "@nestjs/cli@npm:9.1.5"
version: 9.1.7
resolution: "@nestjs/cli@npm:9.1.7"
dependencies:
"@angular-devkit/core": 14.2.2
"@angular-devkit/schematics": 14.2.2
"@angular-devkit/schematics-cli": 14.2.2
"@angular-devkit/core": 15.0.4
"@angular-devkit/schematics": 15.0.4
"@angular-devkit/schematics-cli": 15.0.4
"@nestjs/schematics": ^9.0.0
chalk: 3.0.0
chokidar: 3.5.3
cli-table3: 0.6.2
cli-table3: 0.6.3
commander: 4.1.1
fork-ts-checker-webpack-plugin: 7.2.13
fork-ts-checker-webpack-plugin: 7.2.14
inquirer: 7.3.3
node-emoji: 1.11.0
ora: 5.4.1
@ -1030,14 +999,14 @@ __metadata:
shelljs: 0.8.5
source-map-support: 0.5.21
tree-kill: 1.2.2
tsconfig-paths: 4.1.0
tsconfig-paths: 4.1.1
tsconfig-paths-webpack-plugin: 4.0.0
typescript: 4.8.4
webpack: 5.74.0
typescript: 4.9.4
webpack: 5.75.0
webpack-node-externals: 3.0.0
bin:
nest: bin/nest.js
checksum: 0a832817fff7126ec6f6a32cd1ca6b8db3b21447ca57c54167f989275b7a5914191c1b99442f19c45ceaa3185d2ee46d80c862b242dbfb8b8b239bd049054ac4
checksum: 3386911c8aa657633da31034e377d98122588f1dfc224fc8b9295097b9190a1743ad95d8f93c51e03758ddc8d5d0b58ae019d0dd8bf39d851cbd5761a76f95ca
languageName: node
linkType: hard
@ -1171,17 +1140,69 @@ __metadata:
linkType: hard
"@nestjs/schematics@npm:^9.0.0":
version: 9.0.3
resolution: "@nestjs/schematics@npm:9.0.3"
version: 9.0.4
resolution: "@nestjs/schematics@npm:9.0.4"
dependencies:
"@angular-devkit/core": 14.2.1
"@angular-devkit/schematics": 14.2.1
fs-extra: 10.1.0
"@angular-devkit/core": 15.0.4
"@angular-devkit/schematics": 15.0.4
fs-extra: 11.1.0
jsonc-parser: 3.2.0
pluralize: 8.0.0
peerDependencies:
typescript: ^4.3.5
checksum: 8439f211f1df75e60092a730d62cfeb22b9d51c864a2740ca8723a5e64284fe63375152b430f4c7d7f54d6f6deedea905d4769f864fe64fa0ce90ea1f4683fbe
checksum: c99d3aa4370a1898493ac0038478c16d12cf36d58f398a328d6181d39f1ab48f267fb8f14573c18917de260aebfed11df5aafa0aaa87b68ee891c1c81961ec3e
languageName: node
linkType: hard
"@nestjs/terminus@npm:^9.1.4":
version: 9.1.4
resolution: "@nestjs/terminus@npm:9.1.4"
dependencies:
boxen: 5.1.2
check-disk-space: 3.3.1
peerDependencies:
"@grpc/grpc-js": "*"
"@grpc/proto-loader": "*"
"@mikro-orm/core": "*"
"@mikro-orm/nestjs": "*"
"@nestjs/axios": "*"
"@nestjs/common": 9.x
"@nestjs/core": 9.x
"@nestjs/microservices": "*"
"@nestjs/mongoose": "*"
"@nestjs/sequelize": "*"
"@nestjs/typeorm": "*"
mongoose: "*"
reflect-metadata: 0.1.x
rxjs: 7.x
sequelize: "*"
typeorm: "*"
peerDependenciesMeta:
"@grpc/grpc-js":
optional: true
"@grpc/proto-loader":
optional: true
"@mikro-orm/core":
optional: true
"@mikro-orm/nestjs":
optional: true
"@nestjs/axios":
optional: true
"@nestjs/microservices":
optional: true
"@nestjs/mongoose":
optional: true
"@nestjs/sequelize":
optional: true
"@nestjs/typeorm":
optional: true
mongoose:
optional: true
sequelize:
optional: true
typeorm:
optional: true
checksum: 35b051951953f001e76fba73e99f74b9fdd42c4b66739b980987dc0aa03a59d64652ed7032a0e6731e71ed5c06af80e59c57915def4d79f3a3c7dbf89d5db9d0
languageName: node
linkType: hard
@ -2105,6 +2126,15 @@ __metadata:
languageName: node
linkType: hard
"ansi-align@npm:^3.0.0":
version: 3.0.1
resolution: "ansi-align@npm:3.0.1"
dependencies:
string-width: ^4.1.0
checksum: 6abfa08f2141d231c257162b15292467081fa49a208593e055c866aa0455b57f3a86b5a678c190c618faa79b4c59e254493099cb700dd9cf2293c6be2c8f5d8d
languageName: node
linkType: hard
"ansi-colors@npm:4.1.3":
version: 4.1.3
resolution: "ansi-colors@npm:4.1.3"
@ -2386,6 +2416,22 @@ __metadata:
languageName: node
linkType: hard
"boxen@npm:5.1.2":
version: 5.1.2
resolution: "boxen@npm:5.1.2"
dependencies:
ansi-align: ^3.0.0
camelcase: ^6.2.0
chalk: ^4.1.0
cli-boxes: ^2.2.1
string-width: ^4.2.2
type-fest: ^0.20.2
widest-line: ^3.1.0
wrap-ansi: ^7.0.0
checksum: 82d03e42a72576ff235123f17b7c505372fe05c83f75f61e7d4fa4bcb393897ec95ce766fecb8f26b915f0f7a7227d66e5ec7cef43f5b2bd9d3aeed47ec55877
languageName: node
linkType: hard
"brace-expansion@npm:^1.1.7":
version: 1.1.11
resolution: "brace-expansion@npm:1.1.11"
@ -2588,6 +2634,13 @@ __metadata:
languageName: node
linkType: hard
"check-disk-space@npm:3.3.1":
version: 3.3.1
resolution: "check-disk-space@npm:3.3.1"
checksum: 90b7b77ab932be0c0a24c5f68778d3c0e9179686282b04d84b1272a511a1c55b9f184c98f12b1a1628b832934971d66e63acaa9e3c82f14d9d221a4848b4cf8b
languageName: node
linkType: hard
"chokidar@npm:3.5.3, chokidar@npm:^3.5.3":
version: 3.5.3
resolution: "chokidar@npm:3.5.3"
@ -2659,6 +2712,13 @@ __metadata:
languageName: node
linkType: hard
"cli-boxes@npm:^2.2.1":
version: 2.2.1
resolution: "cli-boxes@npm:2.2.1"
checksum: be79f8ec23a558b49e01311b39a1ea01243ecee30539c880cf14bf518a12e223ef40c57ead0cb44f509bffdffc5c129c746cd50d863ab879385370112af4f585
languageName: node
linkType: hard
"cli-cursor@npm:^3.1.0":
version: 3.1.0
resolution: "cli-cursor@npm:3.1.0"
@ -2675,16 +2735,16 @@ __metadata:
languageName: node
linkType: hard
"cli-table3@npm:0.6.2":
version: 0.6.2
resolution: "cli-table3@npm:0.6.2"
"cli-table3@npm:0.6.3":
version: 0.6.3
resolution: "cli-table3@npm:0.6.3"
dependencies:
"@colors/colors": 1.5.0
string-width: ^4.2.0
dependenciesMeta:
"@colors/colors":
optional: true
checksum: 2f82391698b8a2a2a5e45d2adcfea5d93e557207f90455a8d4c1aac688e9b18a204d9eb4ba1d322fa123b17d64ea3dc5e11de8b005529f3c3e7dbeb27cb4d9be
checksum: 09897f68467973f827c04e7eaadf13b55f8aec49ecd6647cc276386ea660059322e2dd8020a8b6b84d422dbdd619597046fa89cbbbdc95b2cea149a2df7c096c
languageName: node
linkType: hard
@ -3728,9 +3788,9 @@ __metadata:
languageName: node
linkType: hard
"fork-ts-checker-webpack-plugin@npm:7.2.13":
version: 7.2.13
resolution: "fork-ts-checker-webpack-plugin@npm:7.2.13"
"fork-ts-checker-webpack-plugin@npm:7.2.14":
version: 7.2.14
resolution: "fork-ts-checker-webpack-plugin@npm:7.2.14"
dependencies:
"@babel/code-frame": ^7.16.7
chalk: ^4.1.2
@ -3751,7 +3811,7 @@ __metadata:
peerDependenciesMeta:
vue-template-compiler:
optional: true
checksum: 3d4694c6fee4b8b2f213d0d10a3f40da770ca0ed3aa2a3dc8d1e701ad1ecaed3a1507f77a1b0cea6ef80539b04d8e5f5f02560e688d310bcb9e8c81f684d2950
checksum: bf4b44e606677da14c5b8127693897003607e7f13ed93a92991665aea5ad5aa3f5629c022d95dbf9380b40bfc02d34fa42857f298525c7688194d1e94f2a2850
languageName: node
linkType: hard
@ -3792,7 +3852,18 @@ __metadata:
languageName: node
linkType: hard
"fs-extra@npm:10.1.0, fs-extra@npm:^10.0.0":
"fs-extra@npm:11.1.0":
version: 11.1.0
resolution: "fs-extra@npm:11.1.0"
dependencies:
graceful-fs: ^4.2.0
jsonfile: ^6.0.1
universalify: ^2.0.0
checksum: 5ca476103fa1f5ff4a9b3c4f331548f8a3c1881edaae323a4415d3153b5dc11dc6a981c8d1dd93eec8367ceee27b53f8bd27eecbbf66ffcdd04927510c171e7f
languageName: node
linkType: hard
"fs-extra@npm:^10.0.0":
version: 10.1.0
resolution: "fs-extra@npm:10.1.0"
dependencies:
@ -4488,6 +4559,7 @@ __metadata:
"@nestjs/platform-express": ^9.0.0
"@nestjs/schedule": ^2.1.0
"@nestjs/schematics": ^9.0.0
"@nestjs/terminus": ^9.1.4
"@nestjs/testing": ^9.0.0
"@types/cron": ^2.0.0
"@types/express": ^4.17.13
@ -5066,13 +5138,6 @@ __metadata:
languageName: node
linkType: hard
"jsonc-parser@npm:3.1.0":
version: 3.1.0
resolution: "jsonc-parser@npm:3.1.0"
checksum: 81b00c565c60cb1b400523a918d42ad9c7bb3d9cf34c708bf78d37c8c496ecd670c3ff8828f2f60aa6e6627ef4287982794ddf92261ea71e320973c54b29fb22
languageName: node
linkType: hard
"jsonc-parser@npm:3.2.0":
version: 3.2.0
resolution: "jsonc-parser@npm:3.2.0"
@ -5249,12 +5314,12 @@ __metadata:
languageName: node
linkType: hard
"magic-string@npm:0.26.2":
version: 0.26.2
resolution: "magic-string@npm:0.26.2"
"magic-string@npm:0.26.7":
version: 0.26.7
resolution: "magic-string@npm:0.26.7"
dependencies:
sourcemap-codec: ^1.4.8
checksum: b4db4e2b370ac8d9ffc6443a2b591b75364bf1fc9121b5a4068d5b89804abff6709d1fa4a0e0c2d54f2e61e0e44db83efdfe219a5ab0ba6d25ee1f2b51fbed55
checksum: 89b0d60cbb32bbf3d1e23c46ea93db082d18a8230b972027aecb10a40bba51be519ecce0674f995571e3affe917b76b09f59d8dbc9a1b2c9c4102a2b6e8a2b01
languageName: node
linkType: hard
@ -6664,7 +6729,7 @@ __metadata:
languageName: node
linkType: hard
"string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3":
"string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.0.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.2, string-width@npm:^4.2.3":
version: 4.2.3
resolution: "string-width@npm:4.2.3"
dependencies:
@ -7091,7 +7156,7 @@ __metadata:
languageName: node
linkType: hard
"tsconfig-paths@npm:^4.0.0":
"tsconfig-paths@npm:4.1.1, tsconfig-paths@npm:^4.0.0":
version: 4.1.1
resolution: "tsconfig-paths@npm:4.1.1"
dependencies:
@ -7174,17 +7239,7 @@ __metadata:
languageName: node
linkType: hard
"typescript@npm:4.8.4":
version: 4.8.4
resolution: "typescript@npm:4.8.4"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 3e4f061658e0c8f36c820802fa809e0fd812b85687a9a2f5430bc3d0368e37d1c9605c3ce9b39df9a05af2ece67b1d844f9f6ea8ff42819f13bcb80f85629af0
languageName: node
linkType: hard
"typescript@npm:^4.7.4":
"typescript@npm:4.9.4, typescript@npm:^4.7.4":
version: 4.9.4
resolution: "typescript@npm:4.9.4"
bin:
@ -7194,17 +7249,7 @@ __metadata:
languageName: node
linkType: hard
"typescript@patch:typescript@4.8.4#~builtin<compat/typescript>":
version: 4.8.4
resolution: "typescript@patch:typescript@npm%3A4.8.4#~builtin<compat/typescript>::version=4.8.4&hash=0102e9"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 301459fc3eb3b1a38fe91bf96d98eb55da88a9cb17b4ef80b4d105d620f4d547ba776cc27b44cc2ef58b66eda23fe0a74142feb5e79a6fb99f54fc018a696afa
languageName: node
linkType: hard
"typescript@patch:typescript@^4.7.4#~builtin<compat/typescript>":
"typescript@patch:typescript@4.9.4#~builtin<compat/typescript>, typescript@patch:typescript@^4.7.4#~builtin<compat/typescript>":
version: 4.9.4
resolution: "typescript@patch:typescript@npm%3A4.9.4#~builtin<compat/typescript>::version=4.9.4&hash=d73830"
bin:
@ -7391,9 +7436,9 @@ __metadata:
languageName: node
linkType: hard
"webpack@npm:5.74.0":
version: 5.74.0
resolution: "webpack@npm:5.74.0"
"webpack@npm:5.75.0":
version: 5.75.0
resolution: "webpack@npm:5.75.0"
dependencies:
"@types/eslint-scope": ^3.7.3
"@types/estree": ^0.0.51
@ -7424,7 +7469,7 @@ __metadata:
optional: true
bin:
webpack: bin/webpack.js
checksum: 320c41369a75051b19e18c63f408b3dcc481852e992f83d311771c5ec0f05f2946385e8ebef62030cf3587f0a3d2f12779ffdb191569a966847289ba7313f946
checksum: 2bcc5f3c195f375944e8af2f00bf2feea39cb9fda5f763b0d1b00077f1c51783db25c94d3fae96a07dead9fa085e6ae7474417e5ab31719c9776ea5969ceb83a
languageName: node
linkType: hard
@ -7458,6 +7503,15 @@ __metadata:
languageName: node
linkType: hard
"widest-line@npm:^3.1.0":
version: 3.1.0
resolution: "widest-line@npm:3.1.0"
dependencies:
string-width: ^4.0.0
checksum: 03db6c9d0af9329c37d74378ff1d91972b12553c7d72a6f4e8525fe61563fa7adb0b9d6e8d546b7e059688712ea874edd5ded475999abdeedf708de9849310e0
languageName: node
linkType: hard
"windows-release@npm:^4.0.0":
version: 4.0.0
resolution: "windows-release@npm:4.0.0"