From 4bc9f41c748f30a5a94075243d9b747d8ddccbfe Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Wed, 18 Sep 2024 10:15:39 +0200 Subject: [PATCH] feat(amqplibIntegration): Add amqplibIntegration to Node --- .gitignore | 3 + .../node-integration-tests/package.json | 2 + .../suites/tracing/amqplib/constants.ts | 15 +++ .../suites/tracing/amqplib/docker-compose.yml | 16 +++ .../suites/tracing/amqplib/init.ts | 9 ++ .../tracing/amqplib/scenario-message.ts | 19 +++ .../suites/tracing/amqplib/test.ts | 53 ++++++++ .../suites/tracing/amqplib/utils.ts | 38 ++++++ .../node-integration-tests/utils/runner.ts | 10 +- packages/astro/src/index.server.ts | 1 + packages/aws-serverless/src/index.ts | 1 + packages/bun/src/index.ts | 1 + packages/google-cloud-serverless/src/index.ts | 1 + packages/node/package.json | 1 + packages/node/src/index.ts | 1 + .../node/src/integrations/tracing/amqplib.ts | 30 +++++ .../node/src/integrations/tracing/index.ts | 3 + packages/remix/src/index.server.ts | 1 + packages/solidstart/src/server/index.ts | 1 + packages/sveltekit/src/server/index.ts | 1 + yarn.lock | 126 ++++++++++++++++-- 21 files changed, 315 insertions(+), 18 deletions(-) create mode 100644 dev-packages/node-integration-tests/suites/tracing/amqplib/constants.ts create mode 100644 dev-packages/node-integration-tests/suites/tracing/amqplib/docker-compose.yml create mode 100644 dev-packages/node-integration-tests/suites/tracing/amqplib/init.ts create mode 100644 dev-packages/node-integration-tests/suites/tracing/amqplib/scenario-message.ts create mode 100644 dev-packages/node-integration-tests/suites/tracing/amqplib/test.ts create mode 100644 dev-packages/node-integration-tests/suites/tracing/amqplib/utils.ts create mode 100644 packages/node/src/integrations/tracing/amqplib.ts diff --git a/.gitignore b/.gitignore index 3cc2319ea8a9..6d96b6c7678b 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,6 @@ packages/deno/lib.deno.d.ts # gatsby packages/gatsby/gatsby-node.d.ts + +# intellij +*.iml diff --git a/dev-packages/node-integration-tests/package.json b/dev-packages/node-integration-tests/package.json index 8c5a7dfe1bc3..9346a79115a1 100644 --- a/dev-packages/node-integration-tests/package.json +++ b/dev-packages/node-integration-tests/package.json @@ -38,6 +38,7 @@ "@types/mongodb": "^3.6.20", "@types/mysql": "^2.15.21", "@types/pg": "^8.6.5", + "amqplib": "^0.10.4", "apollo-server": "^3.11.1", "axios": "^1.6.7", "connect": "^3.7.0", @@ -65,6 +66,7 @@ "yargs": "^16.2.0" }, "devDependencies": { + "@types/amqplib": "^0.10.5", "@types/node-cron": "^3.0.11", "@types/node-schedule": "^2.1.7", "globby": "11" diff --git a/dev-packages/node-integration-tests/suites/tracing/amqplib/constants.ts b/dev-packages/node-integration-tests/suites/tracing/amqplib/constants.ts new file mode 100644 index 000000000000..b7a3e8f79ea2 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/amqplib/constants.ts @@ -0,0 +1,15 @@ +const amqpUsername = 'sentry'; +const amqpPassword = 'sentry'; + +export const AMQP_URL = `amqp://${amqpUsername}:${amqpPassword}@localhost:5672/`; +export const ACKNOWLEDGEMENT = { noAck: false }; + +export const QUEUE_OPTIONS = { + durable: true, // Make the queue durable + exclusive: false, // Not exclusive + autoDelete: false, // Don't auto-delete the queue + arguments: { + 'x-message-ttl': 30000, // Message TTL of 30 seconds + 'x-max-length': 1000, // Maximum queue length of 1000 messages + }, +}; diff --git a/dev-packages/node-integration-tests/suites/tracing/amqplib/docker-compose.yml b/dev-packages/node-integration-tests/suites/tracing/amqplib/docker-compose.yml new file mode 100644 index 000000000000..dc68d428c976 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/amqplib/docker-compose.yml @@ -0,0 +1,16 @@ +version: '3' + +services: + rabbitmq: + image: rabbitmq:management + container_name: rabbitmq + environment: + - RABBITMQ_DEFAULT_USER=sentry + - RABBITMQ_DEFAULT_PASS=sentry + ports: + - "5672:5672" + - "15672:15672" + +networks: + default: + driver: bridge diff --git a/dev-packages/node-integration-tests/suites/tracing/amqplib/init.ts b/dev-packages/node-integration-tests/suites/tracing/amqplib/init.ts new file mode 100644 index 000000000000..c3fd63415f78 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/amqplib/init.ts @@ -0,0 +1,9 @@ +import { loggingTransport } from '@sentry-internal/node-integration-tests'; +import * as Sentry from '@sentry/node'; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + tracesSampleRate: 1.0, + transport: loggingTransport, +}); diff --git a/dev-packages/node-integration-tests/suites/tracing/amqplib/scenario-message.ts b/dev-packages/node-integration-tests/suites/tracing/amqplib/scenario-message.ts new file mode 100644 index 000000000000..2fa0d0feaa89 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/amqplib/scenario-message.ts @@ -0,0 +1,19 @@ +import * as Sentry from '@sentry/node'; +import './init'; +import { connectToRabbitMQ, consumeMessageFromQueue, createQueue, sendMessageToQueue } from './utils'; + +const queueName = 'queue1'; + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +(async () => { + const { connection, channel } = await connectToRabbitMQ(); + await createQueue(queueName, channel); + + await Sentry.startSpan({ name: 'root span' }, async () => { + sendMessageToQueue(queueName, channel, JSON.stringify({ foo: 'bar01' })); + }); + + await consumeMessageFromQueue(queueName, channel); + await channel.close(); + await connection.close(); +})(); diff --git a/dev-packages/node-integration-tests/suites/tracing/amqplib/test.ts b/dev-packages/node-integration-tests/suites/tracing/amqplib/test.ts new file mode 100644 index 000000000000..a5fea64577eb --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/amqplib/test.ts @@ -0,0 +1,53 @@ +import type { TransactionEvent } from '@sentry/types'; +import { cleanupChildProcesses, createRunner } from '../../../utils/runner'; + +jest.setTimeout(30_000); + +const EXPECTED_MESSAGE_SPAN_PRODUCER = expect.objectContaining({ + op: 'message', + data: expect.objectContaining({ + 'messaging.system': 'rabbitmq', + 'otel.kind': 'PRODUCER', + 'sentry.op': 'message', + }), + status: 'ok', +}); + +const EXPECTED_MESSAGE_SPAN_CONSUMER = expect.objectContaining({ + op: 'message', + data: expect.objectContaining({ + 'messaging.system': 'rabbitmq', + 'otel.kind': 'CONSUMER', + 'sentry.op': 'message', + 'sentry.origin': 'auto.amqplib.otel.consumer', + }), + status: 'ok', +}); + +describe('amqplib auto-instrumentation', () => { + afterAll(async () => { + cleanupChildProcesses(); + }); + + test('should be able to send and receive messages', done => { + createRunner(__dirname, 'scenario-message.ts') + .withDockerCompose({ + workingDirectory: [__dirname], + readyMatches: ['Time to start RabbitMQ'], + }) + .expect({ + transaction: (transaction: TransactionEvent) => { + expect(transaction.transaction).toEqual('root span'); + expect(transaction.spans?.length).toEqual(1); + expect(transaction.spans![0]).toMatchObject(EXPECTED_MESSAGE_SPAN_PRODUCER); + }, + }) + .expect({ + transaction: (transaction: TransactionEvent) => { + expect(transaction.transaction).toEqual('queue1 process'); + expect(transaction.contexts?.trace).toMatchObject(EXPECTED_MESSAGE_SPAN_CONSUMER); + }, + }) + .start(done); + }); +}); diff --git a/dev-packages/node-integration-tests/suites/tracing/amqplib/utils.ts b/dev-packages/node-integration-tests/suites/tracing/amqplib/utils.ts new file mode 100644 index 000000000000..cf6f452365f2 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/amqplib/utils.ts @@ -0,0 +1,38 @@ +import amqp from 'amqplib'; +import type { Channel, Connection } from 'amqplib'; +import { ACKNOWLEDGEMENT, AMQP_URL, QUEUE_OPTIONS } from './constants'; + +export type RabbitMQData = { + connection: Connection; + channel: Channel; +}; + +export async function connectToRabbitMQ(): Promise { + const connection = await amqp.connect(AMQP_URL); + const channel = await connection.createChannel(); + return { connection, channel }; +} + +export async function createQueue(queueName: string, channel: Channel): Promise { + await channel.assertQueue(queueName, QUEUE_OPTIONS); +} + +export function sendMessageToQueue(queueName: string, channel: Channel, message: string): void { + channel.sendToQueue(queueName, Buffer.from(message)); +} + +async function consumer(queueName: string, channel: Channel): Promise { + await channel.consume( + queueName, + message => { + if (message) { + channel.ack(message); + } + }, + ACKNOWLEDGEMENT, + ); +} + +export async function consumeMessageFromQueue(queueName: string, channel: Channel): Promise { + await consumer(queueName, channel); +} diff --git a/dev-packages/node-integration-tests/utils/runner.ts b/dev-packages/node-integration-tests/utils/runner.ts index 76c19074ed9c..bde5bd06cd21 100644 --- a/dev-packages/node-integration-tests/utils/runner.ts +++ b/dev-packages/node-integration-tests/utils/runner.ts @@ -11,6 +11,7 @@ import type { SerializedCheckIn, SerializedSession, SessionAggregates, + TransactionEvent, } from '@sentry/types'; import axios from 'axios'; import { createBasicSentryServer } from './server'; @@ -151,7 +152,7 @@ type Expected = event: Partial | ((event: Event) => void); } | { - transaction: Partial | ((event: Event) => void); + transaction: Partial | ((event: TransactionEvent) => void); } | { session: Partial | ((event: SerializedSession) => void); @@ -317,7 +318,7 @@ export function createRunner(...paths: string[]) { } if ('transaction' in expected) { - const event = item[1] as Event; + const event = item[1] as TransactionEvent; if (typeof expected.transaction === 'function') { expected.transaction(event); } else { @@ -483,6 +484,7 @@ export function createRunner(...paths: string[]) { method: 'get' | 'post', path: string, headers: Record = {}, + data?: any, // axios accept any as data ): Promise { try { await waitFor(() => scenarioServerPort !== undefined); @@ -497,7 +499,7 @@ export function createRunner(...paths: string[]) { if (method === 'get') { await axios.get(url, { headers }); } else { - await axios.post(url, { headers }); + await axios.post(url, data, { headers }); } } catch (e) { return; @@ -506,7 +508,7 @@ export function createRunner(...paths: string[]) { } else if (method === 'get') { return (await axios.get(url, { headers })).data; } else { - return (await axios.post(url, { headers })).data; + return (await axios.post(url, data, { headers })).data; } }, }; diff --git a/packages/astro/src/index.server.ts b/packages/astro/src/index.server.ts index 2645151a9ede..49c186875d3a 100644 --- a/packages/astro/src/index.server.ts +++ b/packages/astro/src/index.server.ts @@ -13,6 +13,7 @@ export { addIntegration, addOpenTelemetryInstrumentation, addRequestDataToEvent, + amqplibIntegration, anrIntegration, captureCheckIn, captureConsoleIntegration, diff --git a/packages/aws-serverless/src/index.ts b/packages/aws-serverless/src/index.ts index 19c90e3aef3f..bbbbcd469e5a 100644 --- a/packages/aws-serverless/src/index.ts +++ b/packages/aws-serverless/src/index.ts @@ -110,6 +110,7 @@ export { addOpenTelemetryInstrumentation, zodErrorsIntegration, profiler, + amqplibIntegration, } from '@sentry/node'; export { diff --git a/packages/bun/src/index.ts b/packages/bun/src/index.ts index fcb3d1331f46..87945f0a18cb 100644 --- a/packages/bun/src/index.ts +++ b/packages/bun/src/index.ts @@ -131,6 +131,7 @@ export { addOpenTelemetryInstrumentation, zodErrorsIntegration, profiler, + amqplibIntegration, } from '@sentry/node'; export { diff --git a/packages/google-cloud-serverless/src/index.ts b/packages/google-cloud-serverless/src/index.ts index 14aa0996cb7c..726ae0a29ae8 100644 --- a/packages/google-cloud-serverless/src/index.ts +++ b/packages/google-cloud-serverless/src/index.ts @@ -110,6 +110,7 @@ export { addOpenTelemetryInstrumentation, zodErrorsIntegration, profiler, + amqplibIntegration, } from '@sentry/node'; export { diff --git a/packages/node/package.json b/packages/node/package.json index dace1125f2e4..f14ead1444b4 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -69,6 +69,7 @@ "@opentelemetry/context-async-hooks": "^1.25.1", "@opentelemetry/core": "^1.25.1", "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/instrumentation-amqplib": "^0.42.0", "@opentelemetry/instrumentation-connect": "0.39.0", "@opentelemetry/instrumentation-express": "0.42.0", "@opentelemetry/instrumentation-fastify": "0.39.0", diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index d4cbcb9544a9..44614a24ac87 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -28,6 +28,7 @@ export { koaIntegration, setupKoaErrorHandler } from './integrations/tracing/koa export { connectIntegration, setupConnectErrorHandler } from './integrations/tracing/connect'; export { spotlightIntegration } from './integrations/spotlight'; export { genericPoolIntegration } from './integrations/tracing/genericPool'; +export { amqplibIntegration } from './integrations/tracing/amqplib'; export { SentryContextManager } from './otel/contextManager'; export { generateInstrumentOnce } from './otel/instrument'; diff --git a/packages/node/src/integrations/tracing/amqplib.ts b/packages/node/src/integrations/tracing/amqplib.ts new file mode 100644 index 000000000000..21a7255b0383 --- /dev/null +++ b/packages/node/src/integrations/tracing/amqplib.ts @@ -0,0 +1,30 @@ +import type { Span } from '@opentelemetry/api'; +import { AmqplibInstrumentation, type AmqplibInstrumentationConfig } from '@opentelemetry/instrumentation-amqplib'; +import { defineIntegration } from '@sentry/core'; +import type { IntegrationFn } from '@sentry/types'; +import { generateInstrumentOnce } from '../../otel/instrument'; +import { addOriginToSpan } from '../../utils/addOriginToSpan'; + +const INTEGRATION_NAME = 'Amqplib'; + +const config: AmqplibInstrumentationConfig = { + consumeEndHook: (span: Span) => { + addOriginToSpan(span, 'auto.amqplib.otel.consumer'); + }, + publishConfirmHook: (span: Span) => { + addOriginToSpan(span, 'auto.amqplib.otel.publisher'); + }, +}; + +export const instrumentAmqplib = generateInstrumentOnce(INTEGRATION_NAME, () => new AmqplibInstrumentation(config)); + +const _amqplibIntegration = (() => { + return { + name: INTEGRATION_NAME, + setupOnce() { + instrumentAmqplib(); + }, + }; +}) satisfies IntegrationFn; + +export const amqplibIntegration = defineIntegration(_amqplibIntegration); diff --git a/packages/node/src/integrations/tracing/index.ts b/packages/node/src/integrations/tracing/index.ts index 69ffc24a8be2..dcfa1126e053 100644 --- a/packages/node/src/integrations/tracing/index.ts +++ b/packages/node/src/integrations/tracing/index.ts @@ -1,6 +1,7 @@ import type { Integration } from '@sentry/types'; import { instrumentHttp } from '../http'; +import { amqplibIntegration, instrumentAmqplib } from './amqplib'; import { connectIntegration, instrumentConnect } from './connect'; import { expressIntegration, instrumentExpress } from './express'; import { fastifyIntegration, instrumentFastify } from './fastify'; @@ -41,6 +42,7 @@ export function getAutoPerformanceIntegrations(): Integration[] { connectIntegration(), genericPoolIntegration(), kafkaIntegration(), + amqplibIntegration(), ]; } @@ -67,5 +69,6 @@ export function getOpenTelemetryInstrumentationToPreload(): (((options?: any) => instrumentGraphql, instrumentRedis, instrumentGenericPool, + instrumentAmqplib, ]; } diff --git a/packages/remix/src/index.server.ts b/packages/remix/src/index.server.ts index 37161b41715e..9218933b9896 100644 --- a/packages/remix/src/index.server.ts +++ b/packages/remix/src/index.server.ts @@ -18,6 +18,7 @@ export { addIntegration, addOpenTelemetryInstrumentation, addRequestDataToEvent, + amqplibIntegration, anrIntegration, captureCheckIn, captureConsoleIntegration, diff --git a/packages/solidstart/src/server/index.ts b/packages/solidstart/src/server/index.ts index 794106eca715..b22fbbe1de0d 100644 --- a/packages/solidstart/src/server/index.ts +++ b/packages/solidstart/src/server/index.ts @@ -9,6 +9,7 @@ export { addIntegration, addOpenTelemetryInstrumentation, addRequestDataToEvent, + amqplibIntegration, anrIntegration, captureCheckIn, captureConsoleIntegration, diff --git a/packages/sveltekit/src/server/index.ts b/packages/sveltekit/src/server/index.ts index e2902afb400b..e9fb6f256192 100644 --- a/packages/sveltekit/src/server/index.ts +++ b/packages/sveltekit/src/server/index.ts @@ -9,6 +9,7 @@ export { addIntegration, addOpenTelemetryInstrumentation, addRequestDataToEvent, + amqplibIntegration, anrIntegration, captureCheckIn, captureConsoleIntegration, diff --git a/yarn.lock b/yarn.lock index 9f6846f29f95..0ecbfdb082f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -58,6 +58,15 @@ resolved "https://registry.yarnpkg.com/@actions/io/-/io-1.1.3.tgz#4cdb6254da7962b07473ff5c335f3da485d94d71" integrity sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q== +"@acuminous/bitsyntax@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@acuminous/bitsyntax/-/bitsyntax-0.1.2.tgz#e0b31b9ee7ad1e4dd840c34864327c33d9f1f653" + integrity sha512-29lUK80d1muEQqiUsSo+3A0yP6CdspgC95EnKBMi22Xlwt79i/En4Vr67+cXhU+cZjbti3TgGGC5wy1stIywVQ== + dependencies: + buffer-more-ints "~1.0.0" + debug "^4.3.4" + safe-buffer "~5.1.2" + "@adobe/css-tools@^4.0.1": version "4.3.3" resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.3.tgz#90749bde8b89cd41764224f5aac29cd4138f75ff" @@ -7070,6 +7079,15 @@ "@opentelemetry/context-base" "^0.12.0" semver "^7.1.3" +"@opentelemetry/instrumentation-amqplib@^0.42.0": + version "0.42.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.42.0.tgz#b3cab5a7207736a30d769962eed3af3838f986c4" + integrity sha512-fiuU6OKsqHJiydHWgTRQ7MnIrJ2lEqsdgFtNIH4LbAUJl/5XmrIeoDzDnox+hfkgWK65jsleFuQDtYb5hW1koQ== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-aws-lambda@0.44.0": version "0.44.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.44.0.tgz#9b82bd6cc86f572be837578b29ef6bf242eb1a39" @@ -9189,6 +9207,13 @@ dependencies: "@types/node" "*" +"@types/amqplib@^0.10.5": + version "0.10.5" + resolved "https://registry.yarnpkg.com/@types/amqplib/-/amqplib-0.10.5.tgz#fd883eddfbd669702a727fa10007b27c4c1e6ec7" + integrity sha512-/cSykxROY7BWwDoi4Y4/jLAuZTshZxd8Ey1QYa/VaXriMotBDoou7V/twJiOSHzU6t1Kp1AHAUXGCgqq+6DNeg== + dependencies: + "@types/node" "*" + "@types/aria-query@^4.2.0": version "4.2.1" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.1.tgz#78b5433344e2f92e8b306c06a5622c50c245bf6b" @@ -9693,8 +9718,17 @@ dependencies: "@types/unist" "*" -"@types/history-4@npm:@types/history@4.7.8", "@types/history-5@npm:@types/history@4.7.8", "@types/history@*": - name "@types/history-4" +"@types/history-4@npm:@types/history@4.7.8": + version "4.7.8" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" + integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== + +"@types/history-5@npm:@types/history@4.7.8": + version "4.7.8" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" + integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== + +"@types/history@*": version "4.7.8" resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== @@ -10022,7 +10056,15 @@ "@types/history" "^3" "@types/react" "*" -"@types/react-router-4@npm:@types/react-router@5.1.14", "@types/react-router-5@npm:@types/react-router@5.1.14": +"@types/react-router-4@npm:@types/react-router@5.1.14": + version "5.1.14" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.14.tgz#e0442f4eb4c446541ad7435d44a97f8fe6df40da" + integrity sha512-LAJpqYUaCTMT2anZheoidiIymt8MuX286zoVFPM3DVb23aQBH0mAkFvzpd4LKqiolV8bBtZWT5Qp7hClCNDENw== + dependencies: + "@types/history" "*" + "@types/react" "*" + +"@types/react-router-5@npm:@types/react-router@5.1.14": version "5.1.14" resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.14.tgz#e0442f4eb4c446541ad7435d44a97f8fe6df40da" integrity sha512-LAJpqYUaCTMT2anZheoidiIymt8MuX286zoVFPM3DVb23aQBH0mAkFvzpd4LKqiolV8bBtZWT5Qp7hClCNDENw== @@ -11481,6 +11523,16 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= +amqplib@^0.10.4: + version "0.10.4" + resolved "https://registry.yarnpkg.com/amqplib/-/amqplib-0.10.4.tgz#4058c775830c908267dc198969015e0e8d280e70" + integrity sha512-DMZ4eCEjAVdX1II2TfIUpJhfKAuoCeDIo/YyETbfAqehHTXxxs7WOOd+N1Xxr4cKhx12y23zk8/os98FxlZHrw== + dependencies: + "@acuminous/bitsyntax" "^0.1.2" + buffer-more-ints "~1.0.0" + readable-stream "1.x >=1.1.9" + url-parse "~1.5.10" + ansi-align@^3.0.0, ansi-align@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" @@ -13494,6 +13546,11 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer-more-ints@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz#ef4f8e2dddbad429ed3828a9c55d44f05c611422" + integrity sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg== + buffer-writer@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" @@ -28425,8 +28482,7 @@ react-is@^18.0.0: dependencies: "@remix-run/router" "1.0.2" -"react-router-6@npm:react-router@6.3.0", react-router@6.3.0: - name react-router-6 +"react-router-6@npm:react-router@6.3.0": version "6.3.0" resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557" integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ== @@ -28441,6 +28497,13 @@ react-router-dom@^6.2.2: history "^5.2.0" react-router "6.3.0" +react-router@6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557" + integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ== + dependencies: + history "^5.2.0" + react@^18.0.0: version "18.0.0" resolved "https://registry.yarnpkg.com/react/-/react-18.0.0.tgz#b468736d1f4a5891f38585ba8e8fb29f91c3cb96" @@ -28556,6 +28619,16 @@ read@^2.0.0: dependencies: mute-stream "~1.0.0" +"readable-stream@1.x >=1.1.9": + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + "readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -29611,7 +29684,7 @@ sade@^1.7.3, sade@^1.8.1: dependencies: mri "^1.1.0" -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1, safe-buffer@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== @@ -30908,7 +30981,16 @@ string-template@~0.2.1: resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" integrity sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0= -"string-width-cjs@npm:string-width@^4.2.0", string-width@4.2.3, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@4.2.3, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -31020,7 +31102,14 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -32838,7 +32927,7 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" -url-parse@^1.5.3: +url-parse@^1.5.3, url-parse@~1.5.10: version "1.5.10" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== @@ -33172,10 +33261,10 @@ vite-plugin-vue-inspector@^5.1.0: kolorist "^1.8.0" magic-string "^0.30.4" -vite@4.5.3: - version "4.5.3" - resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.3.tgz#d88a4529ea58bae97294c7e2e6f0eab39a50fb1a" - integrity sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg== +vite@4.5.5: + version "4.5.5" + resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.5.tgz#639b9feca5c0a3bfe3c60cb630ef28bf219d742e" + integrity sha512-ifW3Lb2sMdX+WU91s3R0FyQlAyLxOzCSCP37ujw0+r5POeHPwe6udWVIElKQq8gk3t7b8rkmvqC6IHBpCff4GQ== dependencies: esbuild "^0.18.10" postcss "^8.4.27" @@ -33989,7 +34078,16 @@ wrangler@^3.67.1: optionalDependencies: fsevents "~2.3.2" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@7.0.0, wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@7.0.0, wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==