Hexagonal, mejora del cliente RMQ y tipos de eventos

This commit is contained in:
2026-01-13 15:41:59 +01:00
parent a6abc24e5f
commit d2db2062b0
20 changed files with 517 additions and 100 deletions

4
.env
View File

@@ -4,8 +4,8 @@ RABBITMQ_PASSWORD=guest
ENVIORMENT=development
RABBITMQ_HOST=rabbitmq-sim-broker
#RABBITMQ_HOST=localhost
#RABBITMQ_HOST=rabbitmq-sim-broker
RABBITMQ_HOST=localhost
RABBITMQ_PORT=5672
RABBITMQ_USER=guest
RABBITMQ_PASSWORD=guest

View File

@@ -4,18 +4,13 @@ WORKDIR /usr/local/app
COPY ./package.json ./yarn.lock ./
RUN corepack enable && \
corepack prepare yarn@4.12.0 --activate
# compilacion del ts -> js
FROM base AS backend
WORKDIR /usr/local/app
EXPOSE ${PORT}
COPY package*.json ./
# copia el codigo en general
COPY tsconfig*.json ./
COPY ./packages ./packages
COPY .env* ./
COPY ./.yarnrc.yml ./
RUN yarn install && yarn cache clean
EXPOSE ${PORT}
CMD ["yarn", "run", "dev"]

View File

@@ -29,8 +29,6 @@ services:
sim-gateway:
container_name: sim-gateway
volumes:
- ./node_modules:/usr/local/node_modules
build:
context: ./
dockerfile: deployment/Dockerfile.dev

View File

@@ -42,7 +42,7 @@
{
"name": "sim.exchange",
"vhost": "sim-vhost",
"type": "direct",
"type": "topic",
"durable": true,
"auto_delete": false,
"internal": false,

View File

@@ -9,7 +9,7 @@
"build": "npx tsc",
"start": "node dist/index.js",
"typecheck": "npx tsc --noEmit",
"dev": "yarn workspaces foreach -A -p run dev",
"dev": "yarn workspaces foreach -Apiv run dev ",
"lint": "eslint .",
"lint:fix": "eslint --fix .",
"format": "prettier --write .",
@@ -27,6 +27,7 @@
"@types/express": "^5.0.6",
"@types/node": "^25.0.3",
"@types/supertest": "^6.0.3",
"concurrently": "^9.2.1",
"prettier": "^3.7.4",
"supertest": "^7.1.4",
"tsx": "^4.21.0",

View File

@@ -0,0 +1,21 @@
/**
* Los eventos de dominion estan orientados a la cola AMQ
*
*/
// Completar con los tipos de evento
export type DomainEventType = string
export type DomainEvent = {
key: string,
payload: Object,
options: Object,
occurredOn: Date,
}
export interface DomainEventSubscriber<T extends DomainEvent> {
subscribedTo(): DomainEventType[];
getEventNames(): string[];
on(domainEvent: T): Promise<void>;
}

View File

@@ -0,0 +1,6 @@
import { DomainEvent, DomainEventSubscriber } from "./DomainEvent";
export interface EventBus {
publish(events: Array<DomainEvent>): Promise<void>;
addSubscribers(subscribers: Array<DomainEventSubscriber<DomainEvent>>): void;
}

View File

@@ -0,0 +1,39 @@
import { DomainEvent } from "./DomainEvent";
export namespace SimEvents {
export type activation = DomainEvent & {
key: "sim.activation",
payload: {
iccid: string
},
options: {
}
}
export type cancelation = DomainEvent & {
key: "sim.cancelation",
payload: {
iccid: string
},
options: {
}
}
export type pause = DomainEvent & {
key: "sim.pause",
payload: {
iccid: string
},
options: {
}
}
export type free = DomainEvent & {
key: "sim.free",
payload: {
iccid: string
},
options: {
}
}
}

View File

@@ -1,24 +1,56 @@
import client, { ChannelModel, ConfirmChannel, connect, Connection } from "amqplib"
import { type ChannelModel, type ConfirmChannel, connect as amqConnect } from "amqplib";
import { DomainEvent, DomainEventSubscriber } from "../domain/DomainEvent";
import { EventBus } from "../domain/EventBus.port";
import { buffer } from "node:stream/consumers";
export type RMQConnectionParams = {
username: string,
password: string,
vhost: string,
hostname: string,
port: number,
secure: boolean
}
const PREFETCH_LIMIT = 1
export class RabbitMQEventBus implements EventBus {
constructor(args: {
connectionParams: RMQConnectionParams
}) {
this.connectionOptions = args.connectionParams
this.checkStructure();
}
export class RabbitConnection {
connection?: ChannelModel
channel?: ConfirmChannel
connected: Boolean = false
private connectionOptions: {
hostname: string,
port: number,
secure: boolean,
username: string,
password: string,
vhost: string
private connectionOptions: RMQConnectionParams
public async connect() {
this.connection = await this.createConnection();
if (this.connection == undefined) throw new Error("[RMQ] Error crecreando la conexion")
this.channel = await this.createConfirmChannel()
}
constructor(opts: typeof this.connectionOptions) {
this.connectionOptions = opts
this.checkStructure();
publish(events: DomainEvent[]): Promise<void> {
return new Promise((res, rej) => {
try {
for (const event of events) {
const exchange = "sim.exchange"
const routingKey = event.key
const content = Buffer.from(JSON.stringify(event))
this.channel?.publish(exchange, routingKey, content)
}
return res()
} catch (err) {
return rej(err)
}
})
}
addSubscribers(subscribers: Array<DomainEventSubscriber<DomainEvent>>): void {
throw new Error("Method not implemented.");
}
/**
@@ -31,19 +63,13 @@ export class RabbitConnection {
this.channel?.assertExchange("sim.exchange", "direct")
}
public async connect() {
this.connection = await this.createConnection();
if (this.connection == undefined) throw new Error("[RMQ] Error crecreando la conexion")
this.channel = await this.createConfirmChannel()
}
protected async createConnection() {
const { hostname, port, secure } = { ...this.connectionOptions }
const { username, password } = { ...this.connectionOptions };
const protocol = secure ? 'amqps' : 'amqp';
const vhost = this.connectionOptions.vhost
const connection = await client.connect({
const connection = await amqConnect({
protocol,
hostname,
port,
@@ -75,4 +101,3 @@ export class RabbitConnection {
}
}

View File

@@ -21,4 +21,3 @@ export const env = {
RABBITMQ_VHOST: String(process.env.RABBITMQ_VHOST),
};
console.log("Consumidor", env)

View File

@@ -11,7 +11,6 @@ const rmqVhost = env.RABBITMQ_VHOST
async function test() {
console.log("iniciado Consumidor", env)
const rbmq = new RabbitConnection({
username: rmqUser,
password: rmqPass,
@@ -26,6 +25,8 @@ async function test() {
await rbmq.channel?.consume("sim.queue", (buff: ConsumeMessage | null) => {
const decoded = buff?.content.toString()
console.log(" [Consumidor] Mensaje recibido ", decoded)
}, {
noAck: true
})
}

View File

@@ -0,0 +1,42 @@
import { EventBus } from "../../shared/domain/EventBus.port";
import { SimEvents } from "../../shared/domain/SimEvents";
/**
* TODO:
* - Conexion con la BDD
* - Conexion con RabbitMQ
* - Pasar a clase cuando existan las conexiones
*/
export class SimUsecases {
private eventBus: EventBus
constructor(args: {
eventBus: EventBus
}
) {
this.eventBus = args.eventBus
}
async activation(args: { iccid: string }) {
const activationEvent = <SimEvents.activation>{
key: "sim.activation",
payload: {
iccid: args.iccid
}
}
return this.eventBus.publish([activationEvent])
}
cancelation(args: { iccid: string }) {
throw new Error("Function not implemented.");
}
pause(args: { iccid: string }) {
throw new Error("Function not implemented.");
}
free(args: { iccid: string }) {
throw new Error("Function not implemented.");
}
}

View File

@@ -0,0 +1,37 @@
import { Request, Response } from "express"
import { SimUsecases } from "aplication/Sim.usecases"
export class SimController {
private simUseCases: SimUsecases
constructor(args: {
simUseCases: SimUsecases
}) {
this.simUseCases = args.simUseCases
}
async activation(req: Request, res: Response) {
const { iccid } = req.body
if (iccid == undefined) {
// TODO: excepcion con nombre se va a repetir
res.status(400).json({
msg: "iccid invalido"
})
}
const resp = await this.simUseCases.activation({ iccid })
}
cancelation(req: Request, res: Response) {
}
pause(req: Request, res: Response) {
}
free(req: Request, res: Response) {
}
}

View File

@@ -0,0 +1,50 @@
import { env } from "#config/env"
import { SimEvents } from "#shared/domain/SimEvents"
import { RabbitMQEventBus, RMQConnectionParams } from "#shared/infrastructure/RabbitMQEventBus"
const rmqUser = env.RABBITMQ_USER
const rmqPass = env.RABBITMQ_PASSWORD
const rmqHost = env.RABBITMQ_HOST
const rmqPort = Number(env.RABBITMQ_PORT)
const rmqSecure = false
const rmqVhost = env.RABBITMQ_VHOST
async function test() {
const connOptions = <RMQConnectionParams>{
username: rmqUser,
password: rmqPass,
vhost: rmqVhost,
hostname: rmqHost,
port: rmqPort,
secure: rmqSecure,
}
const event = <SimEvents.activation>{
key: "sim.activation",
payload: {
iccid: "1234"
},
options: {
}
}
const rmqCli = new RabbitMQEventBus({
connectionParams: connOptions
})
await rmqCli.connect()
console.log("publicando", event)
rmqCli.publish([event])
.then(e => {
console.log("Mensaje publicado", e)
})
.catch(err => console.error)
}
test()
export default {}

View File

@@ -0,0 +1,22 @@
import { Router } from 'express';
const simRoutes = Router()
simRoutes.get("/status")
simRoutes.post("/save", (req, res) => {
})
simRoutes.post("/activate", (req, res) => {
const { iccid } = req.body
})
simRoutes.post("/pause", (req, res) => {
})
simRoutes.post("/cancel", (req, res) => {
})
// Proceso especifico de ALAI para liberar sims canceladas
simRoutes.post("/free", (req, res) => {
})

View File

@@ -1,5 +1,5 @@
{
"name": "sim-gestor-eventos",
"name": "sim-entrada-eventos",
"version": "1.0.0",
"description": "",
"main": "index.ts",

View File

@@ -1,7 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/sim-gestor-eventos",
"outDir": "../../dist/sim-entrada-eventos",
"baseUrl": ".",
"paths": {
"#config/*": [

View File

@@ -1,42 +0,0 @@
import { env } from "#config/env"
import { RabbitConnection } from "#shared/adapters/queues/RabbitMQClient"
const rmqUser = env.RABBITMQ_USER
const rmqPass = env.RABBITMQ_PASSWORD
const rmqHost = env.RABBITMQ_HOST
const rmqPort = Number(env.RABBITMQ_PORT)
const rmqSecure = false
const rmqVhost = env.RABBITMQ_VHOST
console.log("[Generador] Iniciando")
async function test() {
const rbmq = new RabbitConnection({
username: rmqUser,
password: rmqPass,
vhost: String(rmqVhost),
hostname: rmqHost,
port: rmqPort,
secure: rmqSecure
})
await rbmq.connect()
console.log("[Generador] enviando --")
rbmq.channel?.sendToQueue("sim.queue", Buffer.from("test"), {},
function (err, ok) {
if (err !== null)
console.warn('Message nacked!');
else
console.log('Message acked');
}
)
}
test()
export default {}

267
yarn.lock
View File

@@ -729,6 +729,22 @@ __metadata:
languageName: node
linkType: hard
"ansi-regex@npm:^5.0.1":
version: 5.0.1
resolution: "ansi-regex@npm:5.0.1"
checksum: 10/2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b
languageName: node
linkType: hard
"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0":
version: 4.3.0
resolution: "ansi-styles@npm:4.3.0"
dependencies:
color-convert: "npm:^2.0.1"
checksum: 10/b4494dfbfc7e4591b4711a396bd27e540f8153914123dccb4cdbbcb514015ada63a3809f362b9d8d4f6b17a706f1d7bea3c6f974b15fa5ae76b5b502070889ff
languageName: node
linkType: hard
"asap@npm:^2.0.0":
version: 2.0.6
resolution: "asap@npm:2.0.6"
@@ -841,6 +857,16 @@ __metadata:
languageName: node
linkType: hard
"chalk@npm:4.1.2":
version: 4.1.2
resolution: "chalk@npm:4.1.2"
dependencies:
ansi-styles: "npm:^4.1.0"
supports-color: "npm:^7.1.0"
checksum: 10/cb3f3e594913d63b1814d7ca7c9bafbf895f75fbf93b92991980610dfd7b48500af4e3a5d4e3a8f337990a96b168d7eb84ee55efdce965e2ee8efc20f8c8f139
languageName: node
linkType: hard
"chownr@npm:^3.0.0":
version: 3.0.0
resolution: "chownr@npm:3.0.0"
@@ -848,6 +874,33 @@ __metadata:
languageName: node
linkType: hard
"cliui@npm:^8.0.1":
version: 8.0.1
resolution: "cliui@npm:8.0.1"
dependencies:
string-width: "npm:^4.2.0"
strip-ansi: "npm:^6.0.1"
wrap-ansi: "npm:^7.0.0"
checksum: 10/eaa5561aeb3135c2cddf7a3b3f562fc4238ff3b3fc666869ef2adf264be0f372136702f16add9299087fb1907c2e4ec5dbfe83bd24bce815c70a80c6c1a2e950
languageName: node
linkType: hard
"color-convert@npm:^2.0.1":
version: 2.0.1
resolution: "color-convert@npm:2.0.1"
dependencies:
color-name: "npm:~1.1.4"
checksum: 10/fa00c91b4332b294de06b443923246bccebe9fab1b253f7fe1772d37b06a2269b4039a85e309abe1fe11b267b11c08d1d0473fda3badd6167f57313af2887a64
languageName: node
linkType: hard
"color-name@npm:~1.1.4":
version: 1.1.4
resolution: "color-name@npm:1.1.4"
checksum: 10/b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610
languageName: node
linkType: hard
"combined-stream@npm:^1.0.8":
version: 1.0.8
resolution: "combined-stream@npm:1.0.8"
@@ -864,6 +917,23 @@ __metadata:
languageName: node
linkType: hard
"concurrently@npm:^9.2.1":
version: 9.2.1
resolution: "concurrently@npm:9.2.1"
dependencies:
chalk: "npm:4.1.2"
rxjs: "npm:7.8.2"
shell-quote: "npm:1.8.3"
supports-color: "npm:8.1.1"
tree-kill: "npm:1.2.2"
yargs: "npm:17.7.2"
bin:
conc: dist/bin/concurrently.js
concurrently: dist/bin/concurrently.js
checksum: 10/2a6b1acbcdbeb478926b80fd81d0b7e075fa16d78a76ceb43f0478b8aeea1c70781379be2f7d6a2528e51fac48ce4ebb686ae2328e4b35e0b1d17234f121c700
languageName: node
linkType: hard
"content-disposition@npm:^1.0.0":
version: 1.0.1
resolution: "content-disposition@npm:1.0.1"
@@ -970,6 +1040,13 @@ __metadata:
languageName: node
linkType: hard
"emoji-regex@npm:^8.0.0":
version: 8.0.0
resolution: "emoji-regex@npm:8.0.0"
checksum: 10/c72d67a6821be15ec11997877c437491c313d924306b8da5d87d2a2bcc2cec9903cb5b04ee1a088460501d8e5b44f10df82fdc93c444101a7610b80c8b6938e1
languageName: node
linkType: hard
"encodeurl@npm:^2.0.0":
version: 2.0.0
resolution: "encodeurl@npm:2.0.0"
@@ -1131,6 +1208,13 @@ __metadata:
languageName: node
linkType: hard
"escalade@npm:^3.1.1":
version: 3.2.0
resolution: "escalade@npm:3.2.0"
checksum: 10/9d7169e3965b2f9ae46971afa392f6e5a25545ea30f2e2dd99c9b0a95a3f52b5653681a84f5b2911a413ddad2d7a93d3514165072f349b5ffc59c75a899970d6
languageName: node
linkType: hard
"escape-html@npm:^1.0.3":
version: 1.0.3
resolution: "escape-html@npm:1.0.3"
@@ -1317,6 +1401,13 @@ __metadata:
languageName: node
linkType: hard
"get-caller-file@npm:^2.0.5":
version: 2.0.5
resolution: "get-caller-file@npm:2.0.5"
checksum: 10/b9769a836d2a98c3ee734a88ba712e62703f1df31b94b784762c433c27a386dd6029ff55c2a920c392e33657d80191edbf18c61487e198844844516f843496b9
languageName: node
linkType: hard
"get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0":
version: 1.3.1
resolution: "get-intrinsic@npm:1.3.1"
@@ -1382,6 +1473,13 @@ __metadata:
languageName: node
linkType: hard
"has-flag@npm:^4.0.0":
version: 4.0.0
resolution: "has-flag@npm:4.0.0"
checksum: 10/261a1357037ead75e338156b1f9452c016a37dcd3283a972a30d9e4a87441ba372c8b81f818cd0fbcd9c0354b4ae7e18b9e1afa1971164aef6d18c2b6095a8ad
languageName: node
linkType: hard
"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0":
version: 1.1.0
resolution: "has-symbols@npm:1.1.0"
@@ -1493,6 +1591,13 @@ __metadata:
languageName: node
linkType: hard
"is-fullwidth-code-point@npm:^3.0.0":
version: 3.0.0
resolution: "is-fullwidth-code-point@npm:3.0.0"
checksum: 10/44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348
languageName: node
linkType: hard
"is-promise@npm:^4.0.0":
version: 4.0.0
resolution: "is-promise@npm:4.0.0"
@@ -1923,6 +2028,13 @@ __metadata:
languageName: node
linkType: hard
"require-directory@npm:^2.1.1":
version: 2.1.1
resolution: "require-directory@npm:2.1.1"
checksum: 10/a72468e2589270d91f06c7d36ec97a88db53ae5d6fe3787fadc943f0b0276b10347f89b363b2a82285f650bdcc135ad4a257c61bdd4d00d6df1fa24875b0ddaf
languageName: node
linkType: hard
"requires-port@npm:^1.0.0":
version: 1.0.0
resolution: "requires-port@npm:1.0.0"
@@ -2047,6 +2159,15 @@ __metadata:
languageName: node
linkType: hard
"rxjs@npm:7.8.2":
version: 7.8.2
resolution: "rxjs@npm:7.8.2"
dependencies:
tslib: "npm:^2.1.0"
checksum: 10/03dff09191356b2b87d94fbc1e97c4e9eb3c09d4452399dddd451b09c2f1ba8d56925a40af114282d7bc0c6fe7514a2236ca09f903cf70e4bbf156650dddb49d
languageName: node
linkType: hard
"safer-buffer@npm:>= 2.1.2 < 3.0.0":
version: 2.1.2
resolution: "safer-buffer@npm:2.1.2"
@@ -2101,6 +2222,13 @@ __metadata:
languageName: node
linkType: hard
"shell-quote@npm:1.8.3":
version: 1.8.3
resolution: "shell-quote@npm:1.8.3"
checksum: 10/5473e354637c2bd698911224129c9a8961697486cff1fb221f234d71c153fc377674029b0223d1d3c953a68d451d79366abfe53d1a0b46ee1f28eb9ade928f4c
languageName: node
linkType: hard
"side-channel-list@npm:^1.0.0":
version: 1.0.0
resolution: "side-channel-list@npm:1.0.0"
@@ -2178,29 +2306,9 @@ __metadata:
languageName: unknown
linkType: soft
"sim-eventos@workspace:.":
"sim-entrada-eventos@workspace:packages/sim-entrada-eventos":
version: 0.0.0-use.local
resolution: "sim-eventos@workspace:."
dependencies:
"@tsconfig/node22": "npm:^22.0.5"
"@types/cors": "npm:^2.8.19"
"@types/express": "npm:^5.0.6"
"@types/node": "npm:^25.0.3"
"@types/supertest": "npm:^6.0.3"
cors: "npm:^2.8.5"
dotenv: "npm:^17.2.3"
express: "npm:^5.2.1"
prettier: "npm:^3.7.4"
supertest: "npm:^7.1.4"
tsx: "npm:^4.21.0"
typescript: "npm:^5.9.3"
vitest: "npm:^4.0.16"
languageName: unknown
linkType: soft
"sim-gestor-eventos@workspace:packages/sim-gestor-eventos":
version: 0.0.0-use.local
resolution: "sim-gestor-eventos@workspace:packages/sim-gestor-eventos"
resolution: "sim-entrada-eventos@workspace:packages/sim-entrada-eventos"
dependencies:
"@tsconfig/node22": "npm:*"
"@types/amqplib": "npm:^0.10.8"
@@ -2220,6 +2328,27 @@ __metadata:
languageName: unknown
linkType: soft
"sim-eventos@workspace:.":
version: 0.0.0-use.local
resolution: "sim-eventos@workspace:."
dependencies:
"@tsconfig/node22": "npm:^22.0.5"
"@types/cors": "npm:^2.8.19"
"@types/express": "npm:^5.0.6"
"@types/node": "npm:^25.0.3"
"@types/supertest": "npm:^6.0.3"
concurrently: "npm:^9.2.1"
cors: "npm:^2.8.5"
dotenv: "npm:^17.2.3"
express: "npm:^5.2.1"
prettier: "npm:^3.7.4"
supertest: "npm:^7.1.4"
tsx: "npm:^4.21.0"
typescript: "npm:^5.9.3"
vitest: "npm:^4.0.16"
languageName: unknown
linkType: soft
"sim-shared@workspace:packages/shared":
version: 0.0.0-use.local
resolution: "sim-shared@workspace:packages/shared"
@@ -2329,6 +2458,26 @@ __metadata:
languageName: node
linkType: hard
"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:
emoji-regex: "npm:^8.0.0"
is-fullwidth-code-point: "npm:^3.0.0"
strip-ansi: "npm:^6.0.1"
checksum: 10/e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb
languageName: node
linkType: hard
"strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1":
version: 6.0.1
resolution: "strip-ansi@npm:6.0.1"
dependencies:
ansi-regex: "npm:^5.0.1"
checksum: 10/ae3b5436d34fadeb6096367626ce987057713c566e1e7768818797e00ac5d62023d0f198c4e681eae9e20701721980b26a64a8f5b91238869592a9c6800719a2
languageName: node
linkType: hard
"superagent@npm:^10.3.0":
version: 10.3.0
resolution: "superagent@npm:10.3.0"
@@ -2357,6 +2506,24 @@ __metadata:
languageName: node
linkType: hard
"supports-color@npm:8.1.1":
version: 8.1.1
resolution: "supports-color@npm:8.1.1"
dependencies:
has-flag: "npm:^4.0.0"
checksum: 10/157b534df88e39c5518c5e78c35580c1eca848d7dbaf31bbe06cdfc048e22c7ff1a9d046ae17b25691128f631a51d9ec373c1b740c12ae4f0de6e292037e4282
languageName: node
linkType: hard
"supports-color@npm:^7.1.0":
version: 7.2.0
resolution: "supports-color@npm:7.2.0"
dependencies:
has-flag: "npm:^4.0.0"
checksum: 10/c8bb7afd564e3b26b50ca6ee47572c217526a1389fe018d00345856d4a9b08ffbd61fadaf283a87368d94c3dcdb8f5ffe2650a5a65863e21ad2730ca0f05210a
languageName: node
linkType: hard
"tar@npm:^7.5.2":
version: 7.5.2
resolution: "tar@npm:7.5.2"
@@ -2408,6 +2575,22 @@ __metadata:
languageName: node
linkType: hard
"tree-kill@npm:1.2.2":
version: 1.2.2
resolution: "tree-kill@npm:1.2.2"
bin:
tree-kill: cli.js
checksum: 10/49117f5f410d19c84b0464d29afb9642c863bc5ba40fcb9a245d474c6d5cc64d1b177a6e6713129eb346b40aebb9d4631d967517f9fbe8251c35b21b13cd96c7
languageName: node
linkType: hard
"tslib@npm:^2.1.0":
version: 2.8.1
resolution: "tslib@npm:2.8.1"
checksum: 10/3e2e043d5c2316461cb54e5c7fe02c30ef6dccb3384717ca22ae5c6b5bc95232a6241df19c622d9c73b809bea33b187f6dbc73030963e29950c2141bc32a79f7
languageName: node
linkType: hard
"tsx@npm:*, tsx@npm:^4.21.0":
version: 4.21.0
resolution: "tsx@npm:4.21.0"
@@ -2641,6 +2824,17 @@ __metadata:
languageName: node
linkType: hard
"wrap-ansi@npm:^7.0.0":
version: 7.0.0
resolution: "wrap-ansi@npm:7.0.0"
dependencies:
ansi-styles: "npm:^4.0.0"
string-width: "npm:^4.1.0"
strip-ansi: "npm:^6.0.0"
checksum: 10/cebdaeca3a6880da410f75209e68cd05428580de5ad24535f22696d7d9cab134d1f8498599f344c3cf0fb37c1715807a183778d8c648d6cc0cb5ff2bb4236540
languageName: node
linkType: hard
"wrappy@npm:1":
version: 1.0.2
resolution: "wrappy@npm:1.0.2"
@@ -2648,6 +2842,13 @@ __metadata:
languageName: node
linkType: hard
"y18n@npm:^5.0.5":
version: 5.0.8
resolution: "y18n@npm:5.0.8"
checksum: 10/5f1b5f95e3775de4514edbb142398a2c37849ccfaf04a015be5d75521e9629d3be29bd4432d23c57f37e5b61ade592fb0197022e9993f81a06a5afbdcda9346d
languageName: node
linkType: hard
"yallist@npm:^4.0.0":
version: 4.0.0
resolution: "yallist@npm:4.0.0"
@@ -2661,3 +2862,25 @@ __metadata:
checksum: 10/1884d272d485845ad04759a255c71775db0fac56308764b4c77ea56a20d56679fad340213054c8c9c9c26fcfd4c4b2a90df993b7e0aaf3cdb73c618d1d1a802a
languageName: node
linkType: hard
"yargs-parser@npm:^21.1.1":
version: 21.1.1
resolution: "yargs-parser@npm:21.1.1"
checksum: 10/9dc2c217ea3bf8d858041252d43e074f7166b53f3d010a8c711275e09cd3d62a002969a39858b92bbda2a6a63a585c7127014534a560b9c69ed2d923d113406e
languageName: node
linkType: hard
"yargs@npm:17.7.2":
version: 17.7.2
resolution: "yargs@npm:17.7.2"
dependencies:
cliui: "npm:^8.0.1"
escalade: "npm:^3.1.1"
get-caller-file: "npm:^2.0.5"
require-directory: "npm:^2.1.1"
string-width: "npm:^4.2.3"
y18n: "npm:^5.0.5"
yargs-parser: "npm:^21.1.1"
checksum: 10/abb3e37678d6e38ea85485ed86ebe0d1e3464c640d7d9069805ea0da12f69d5a32df8e5625e370f9c96dd1c2dc088ab2d0a4dd32af18222ef3c4224a19471576
languageName: node
linkType: hard