From 4b2653117203001174e57032639731a857303950 Mon Sep 17 00:00:00 2001 From: Richard R Date: Wed, 20 May 2026 07:38:03 -0600 Subject: [PATCH] chore(worker): migrate compute worker from Redis/BullMQ to NATS JetStream Replace Redis and BullMQ with NATS JetStream and KV for job queuing and state management in the compute worker service. Update environment variables, Docker Compose, and documentation to reflect the new message queue backend. Adjust dependencies and code to use NATS-based work queue and key-value storage for durable job processing. This change improves scalability and reliability of distributed compute workloads by leveraging NATS JetStream's work queue and persistence features. Documentation and configuration examples are updated to guide deployments using the new backend. --- .env.example | 2 +- README.md | 4 +- compute/worker/.env.example | 5 +- compute/worker/docker-compose.yml | 19 +- compute/worker/package.json | 11 +- compute/worker/src/server.ts | 667 ++++++++----- docs-site/docs/deploy/compute-worker.md | 8 +- docs-site/docs/deploy/local-development.md | 8 +- docs-site/docs/deploy/vercel-deployment.md | 2 +- docs-site/docs/docker-quick-start.md | 2 +- docs-site/docs/introduction.md | 2 +- .../docs/reference/environment-variables.md | 4 +- docs-site/docs/reference/stack.md | 4 +- pnpm-lock.yaml | 919 ++++++++++++++---- 14 files changed, 1184 insertions(+), 473 deletions(-) diff --git a/.env.example b/.env.example index 7457a88..88f6ec0 100644 --- a/.env.example +++ b/.env.example @@ -79,7 +79,7 @@ IMPORT_LIBRARY_DIRS= # Heavy compute backend mode for ONNX whisper alignment + PDF layout parsing. # local = run compute in-process (default) -# worker = external durable worker mode (requires Redis-backed compute-worker service) +# worker = external durable worker mode (requires NATS JetStream-backed compute-worker service) COMPUTE_MODE=local # Required when COMPUTE_MODE=worker # COMPUTE_WORKER_URL=http://localhost:8081 diff --git a/README.md b/README.md index ee8d95a..1e6b1ad 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ OpenReader is an open source, self-host-friendly text-to-speech document reader ## ✨ Highlights - 🧱 **Layout-aware PDF parsing** with PP-DocLayoutV3 (ONNX) — structured block detection, cross-page stitching, and geometry-based highlighting for precise read-along sync. -- ⏱️ **Word-by-word highlighting** via built-in ONNX Whisper alignment — no external dependencies, runs in-process (`COMPUTE_MODE=local`) or offloaded to a scalable Redis-backed worker (`COMPUTE_MODE=worker`). +- ⏱️ **Word-by-word highlighting** via built-in ONNX Whisper alignment — no external dependencies, runs in-process (`COMPUTE_MODE=local`) or offloaded to a scalable NATS JetStream-backed worker (`COMPUTE_MODE=worker`). - ⚡ **Segment-based read-along** for EPUB, PDF, TXT, MD, and DOCX — sentence-aware TTS with cached audio segments, background preloading, and resumable playback. - 🎯 **Multi-provider TTS** — self-hosted OpenAI-compatible servers (Kokoro-FastAPI, KittenTTS-FastAPI, Orpheus-FastAPI) or cloud APIs (OpenAI, Replicate, DeepInfra). - 🎧 **Audiobook export** in `m4b`/`mp3` with resumable chapter processing. @@ -32,7 +32,7 @@ OpenReader is an open source, self-host-friendly text-to-speech document reader | --- | --- | | Run with Docker | [Docker Quick Start](https://docs.openreader.richardr.dev/docker-quick-start) | | Deploy on Vercel | [Vercel Deployment](https://docs.openreader.richardr.dev/deploy/vercel-deployment) | -| Deploy external compute worker | [Compute Worker (Redis + BullMQ)](https://docs.openreader.richardr.dev/deploy/compute-worker) | +| Deploy external compute worker | [Compute Worker (NATS JetStream)](https://docs.openreader.richardr.dev/deploy/compute-worker) | | Develop locally | [Local Development](https://docs.openreader.richardr.dev/deploy/local-development) | | Configure auth | [Auth](https://docs.openreader.richardr.dev/configure/auth) | | Configure SQL database | [Database and Migrations](https://docs.openreader.richardr.dev/configure/database) | diff --git a/compute/worker/.env.example b/compute/worker/.env.example index 4809e98..4a36fdc 100644 --- a/compute/worker/.env.example +++ b/compute/worker/.env.example @@ -7,8 +7,8 @@ COMPUTE_LOG_FORMAT=pretty # App <-> worker auth COMPUTE_WORKER_TOKEN=local-compute-token -# Redis/BullMQ -REDIS_URL=redis://redis:6379 +# NATS/JetStream +NATS_URL=nats://nats:4222 # Shared object storage (must be reachable from worker) S3_BUCKET=openreader-documents @@ -21,5 +21,4 @@ S3_ENDPOINT=http://host.docker.internal:8333 S3_FORCE_PATH_STYLE=true # Queue + execution tuning -COMPUTE_QUEUE_MAX_DEPTH=64 COMPUTE_PREWARM_MODELS=true diff --git a/compute/worker/docker-compose.yml b/compute/worker/docker-compose.yml index 067b2c6..269c2d7 100644 --- a/compute/worker/docker-compose.yml +++ b/compute/worker/docker-compose.yml @@ -1,9 +1,13 @@ services: - redis: - image: redis:7-alpine - container_name: openreader-compute-redis + nats: + image: nats:2.14-alpine + container_name: openreader-compute-nats + command: ["-js", "-sd", "/data"] ports: - - "6379:6379" + - "4222:4222" + - "8222:8222" + volumes: + - nats-data:/data compute-worker: build: @@ -11,11 +15,11 @@ services: dockerfile: compute/worker/Dockerfile container_name: openreader-compute-worker depends_on: - - redis + - nats env_file: - ./.env environment: - REDIS_URL: ${REDIS_URL:-redis://redis:6379} + NATS_URL: ${NATS_URL:-nats://nats:4222} COMPUTE_WORKER_HOST: ${COMPUTE_WORKER_HOST:-0.0.0.0} COMPUTE_WORKER_PORT: ${COMPUTE_WORKER_PORT:-8081} COMPUTE_WORKER_TOKEN: ${COMPUTE_WORKER_TOKEN:-local-compute-token} @@ -39,3 +43,6 @@ services: path: ../../pnpm-lock.yaml - action: rebuild path: ../../pnpm-workspace.yaml + +volumes: + nats-data: diff --git a/compute/worker/package.json b/compute/worker/package.json index a904a29..bd85999 100644 --- a/compute/worker/package.json +++ b/compute/worker/package.json @@ -8,16 +8,17 @@ "start": "tsx src/server.ts" }, "dependencies": { - "@aws-sdk/client-s3": "^3.1045.0", + "@aws-sdk/client-s3": "^3.1050.0", + "@nats-io/jetstream": "^3.4.0", + "@nats-io/kv": "^3.4.0", + "@nats-io/transport-node": "^3.4.0", "@openreader/compute-core": "workspace:*", - "bullmq": "^5.61.2", "fastify": "^5.6.2", - "ioredis": "^5.8.2", - "pino": "^9.14.0", + "pino": "^10.3.1", "pino-pretty": "^13.1.2", "zod": "^4.1.12" }, "devDependencies": { - "tsx": "^4.20.6" + "tsx": "^4.22.3" } } diff --git a/compute/worker/src/server.ts b/compute/worker/src/server.ts index ebbfcf8..8b4263b 100644 --- a/compute/worker/src/server.ts +++ b/compute/worker/src/server.ts @@ -1,10 +1,25 @@ -import Fastify, { type FastifyReply, type FastifyRequest } from 'fastify'; -import { Queue, Worker, type Job, type JobsOptions } from 'bullmq'; -import IORedis from 'ioredis'; +import Fastify, { type FastifyRequest } from 'fastify'; import { z } from 'zod'; import { - ALIGN_QUEUE_NAME, - PDF_LAYOUT_QUEUE_NAME, + connect, + nanos, + type NatsConnection, +} from '@nats-io/transport-node'; +import { + AckPolicy, + DeliverPolicy, + ReplayPolicy, + RetentionPolicy, + StorageType, + jetstream, + jetstreamManager, + type Consumer, + type JetStreamClient, + type JetStreamManager, + type JsMsg, +} from '@nats-io/jetstream'; +import { Kvm, type KV } from '@nats-io/kv'; +import { ensureComputeModels, runPdfLayoutFromPdfBuffer, runWhisperAlignmentFromAudioBuffer, @@ -17,6 +32,33 @@ import { } from '@openreader/compute-core'; import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3'; +const JOBS_STREAM_NAME = 'compute_jobs'; +const WHISPER_JOBS_SUBJECT = 'jobs.whisper'; +const LAYOUT_JOBS_SUBJECT = 'jobs.layout'; +const WHISPER_CONSUMER_NAME = 'compute_whisper'; +const LAYOUT_CONSUMER_NAME = 'compute_layout'; +const JOB_STATES_BUCKET = 'job_states'; +const JOB_STATES_TTL_MS = 24 * 60 * 60 * 1000; +const PULL_EXPIRES_MS = 1000; +const LOOP_ERROR_BACKOFF_MS = 500; + +interface QueuedJob { + jobId: string; + queuedAt: number; + payload: TPayload; +} + +interface StoredJobState extends WorkerJobStatusResponse { + timestamp: number; + startedAt?: number; + updatedAt: number; +} + +type JsonCodec = { + encode(value: T): Uint8Array; + decode(data: Uint8Array): T; +}; + function requireEnv(name: string): string { const value = process.env[name]?.trim(); if (!value) throw new Error(`${name} is required`); @@ -126,12 +168,6 @@ async function withTimeout(promise: Promise, timeoutMs: number, label: str } } -function parseRetryAfterSeconds(raw: string | undefined): number { - const parsed = Number(raw ?? ''); - if (!Number.isFinite(parsed) || parsed <= 0) return 2; - return Math.max(1, Math.floor(parsed)); -} - function isAuthed(request: FastifyRequest, expectedToken: string): boolean { const auth = request.headers.authorization; if (!auth?.startsWith('Bearer ')) return false; @@ -139,6 +175,34 @@ function isAuthed(request: FastifyRequest, expectedToken: string): boolean { return token === expectedToken; } +function safeDurationMs(start: number | undefined, end: number | undefined): number | undefined { + if (!Number.isFinite(start) || !Number.isFinite(end)) return undefined; + return Math.max(0, Math.floor((end as number) - (start as number))); +} + +function toErrorMessage(error: unknown): string { + if (error instanceof Error && error.message) return error.message; + return String(error); +} + +function isAlreadyExistsError(error: unknown): boolean { + const message = toErrorMessage(error).toLowerCase(); + return message.includes('already in use') || message.includes('already exists'); +} + +function createJsonCodec(): JsonCodec { + const encoder = new TextEncoder(); + const decoder = new TextDecoder(); + return { + encode(value: T): Uint8Array { + return encoder.encode(JSON.stringify(value)); + }, + decode(data: Uint8Array): T { + return JSON.parse(decoder.decode(data)) as T; + }, + }; +} + const alignSchema = z.object({ text: z.string().trim().min(1), lang: z.string().trim().min(1).max(16).optional(), @@ -152,83 +216,194 @@ const layoutSchema = z.object({ documentObjectKey: z.string().trim().min(1).max(2048), }); -function mapJobState(job: Job): WorkerJobStatusResponse { - const result = job.returnvalue as Result | undefined; - const resultTiming = readResultTiming(result); - const timing = buildJobTimingSnapshot(job, resultTiming); - - if (job.failedReason) { - return { - status: 'failed', - error: { - message: job.failedReason || 'Worker job failed', - }, - ...(timing ? { timing } : {}), - }; - } - if (typeof job.returnvalue !== 'undefined' && job.finishedOn) { - return { - status: 'succeeded', - result: job.returnvalue as Result, - ...(timing ? { timing } : {}), - }; - } - - if (job.processedOn) { - return { - status: 'running', - ...(timing ? { timing } : {}), - }; - } - return { - status: 'queued', - ...(timing ? { timing } : {}), - }; +async function putState( + kv: KV, + codec: JsonCodec>, + jobId: string, + state: StoredJobState, +): Promise { + await kv.put(jobId, codec.encode(state)); } -function readResultTiming(result: Result | undefined): WorkerJobTiming | undefined { - if (!result || typeof result !== 'object') return undefined; - const maybe = result as { timing?: WorkerJobTiming }; - if (!maybe.timing || typeof maybe.timing !== 'object') return undefined; - return maybe.timing; +async function getState( + kv: KV, + codec: JsonCodec>, + jobId: string, +): Promise | null> { + const entry = await kv.get(jobId); + if (!entry || entry.operation !== 'PUT') return null; + return codec.decode(entry.value); } -function toSafeDurationMs(start: number | undefined, end: number | undefined): number | undefined { - if (!Number.isFinite(start) || !Number.isFinite(end)) return undefined; - return Math.max(0, Math.floor((end as number) - (start as number))); -} - -function buildJobTimingSnapshot(job: Job, base?: WorkerJobTiming): WorkerJobTiming | undefined { - const now = Date.now(); - const timestamp = typeof job.timestamp === 'number' ? job.timestamp : undefined; - const processedOn = typeof job.processedOn === 'number' ? job.processedOn : undefined; - - const timing: WorkerJobTiming = { - ...(base ?? {}), +async function ensureJetStreamResources( + jsm: JetStreamManager, + whisperTimeoutMs: number, + pdfTimeoutMs: number, + attempts: number, +): Promise { + const streamConfig = { + name: JOBS_STREAM_NAME, + subjects: [WHISPER_JOBS_SUBJECT, LAYOUT_JOBS_SUBJECT], + retention: RetentionPolicy.Workqueue, + storage: StorageType.File, }; - if (typeof timing.queueWaitMs !== 'number') { - timing.queueWaitMs = processedOn - ? toSafeDurationMs(timestamp, processedOn) - : toSafeDurationMs(timestamp, now); + try { + await jsm.streams.add(streamConfig); + } catch (error) { + if (!isAlreadyExistsError(error)) throw error; + await jsm.streams.update(JOBS_STREAM_NAME, { + subjects: [WHISPER_JOBS_SUBJECT, LAYOUT_JOBS_SUBJECT], + }); } - const hasAnyTiming = Object.values(timing).some((value) => typeof value === 'number' && Number.isFinite(value)); - return hasAnyTiming ? timing : undefined; + const ensureConsumer = async (name: string, subject: string, ackWaitMs: number): Promise => { + const config = { + durable_name: name, + ack_policy: AckPolicy.Explicit, + deliver_policy: DeliverPolicy.All, + replay_policy: ReplayPolicy.Instant, + filter_subject: subject, + ack_wait: nanos(Math.max(ackWaitMs, 1_000)), + max_deliver: attempts, + }; + + try { + await jsm.consumers.add(JOBS_STREAM_NAME, config); + } catch (error) { + if (!isAlreadyExistsError(error)) throw error; + await jsm.consumers.update(JOBS_STREAM_NAME, name, { + filter_subject: subject, + ack_wait: nanos(Math.max(ackWaitMs, 1_000)), + max_deliver: attempts, + }); + } + }; + + await Promise.all([ + ensureConsumer(WHISPER_CONSUMER_NAME, WHISPER_JOBS_SUBJECT, whisperTimeoutMs + 15_000), + ensureConsumer(LAYOUT_CONSUMER_NAME, LAYOUT_JOBS_SUBJECT, pdfTimeoutMs + 15_000), + ]); } -async function getQueueDepth(queue: Queue): Promise { - const counts = await queue.getJobCounts('waiting', 'active', 'prioritized', 'delayed'); - return (counts.waiting ?? 0) + (counts.active ?? 0) + (counts.prioritized ?? 0) + (counts.delayed ?? 0); +async function createWorkerLoop(input: { + consumer: Consumer; + kv: KV; + stateCodec: JsonCodec>; + jobCodec: JsonCodec>; + run: (payload: TPayload, queueWaitMs: number) => Promise; + maxAttempts: number; + logLabel: string; + shouldStop: () => boolean; + log: { + error: (obj: Record, msg: string) => void; + info: (obj: Record, msg: string) => void; + }; +}): Promise { + while (!input.shouldStop()) { + let msg: JsMsg | null = null; + try { + msg = await input.consumer.next({ expires: PULL_EXPIRES_MS }); + } catch (error) { + if (input.shouldStop()) return; + input.log.error({ error: toErrorMessage(error), worker: input.logLabel }, 'worker pull failed'); + await new Promise((resolve) => setTimeout(resolve, LOOP_ERROR_BACKOFF_MS)); + continue; + } + + if (!msg) continue; + + let decoded: QueuedJob | null = null; + try { + const job = input.jobCodec.decode(msg.data); + decoded = job; + const startedAt = Date.now(); + const queueWaitMs = safeDurationMs(job.queuedAt, startedAt); + + await putState(input.kv, input.stateCodec, job.jobId, { + status: 'running', + timestamp: job.queuedAt, + startedAt, + updatedAt: startedAt, + ...(typeof queueWaitMs === 'number' ? { timing: { queueWaitMs } } : {}), + }); + + const result = await input.run(job.payload, queueWaitMs ?? 0); + const resultTiming = result && typeof result === 'object' && 'timing' in result + ? (result as { timing?: WorkerJobTiming }).timing + : undefined; + + await putState(input.kv, input.stateCodec, job.jobId, { + status: 'succeeded', + timestamp: job.queuedAt, + startedAt, + updatedAt: Date.now(), + result, + ...(resultTiming ? { timing: resultTiming } : {}), + }); + + msg.ack(); + input.log.info({ worker: input.logLabel, jobId: job.jobId, timing: resultTiming }, 'job succeeded'); + } catch (error) { + const message = toErrorMessage(error); + const deliveryCount = msg.info.deliveryCount; + const hasRetriesLeft = deliveryCount < input.maxAttempts; + + if (decoded?.jobId) { + const now = Date.now(); + const queueWaitMs = safeDurationMs(decoded.queuedAt, now); + const state: StoredJobState = hasRetriesLeft + ? { + status: 'running', + timestamp: decoded.queuedAt, + updatedAt: now, + ...(typeof queueWaitMs === 'number' ? { timing: { queueWaitMs } } : {}), + } + : { + status: 'failed', + timestamp: decoded.queuedAt, + updatedAt: now, + error: { message }, + ...(typeof queueWaitMs === 'number' ? { timing: { queueWaitMs } } : {}), + }; + + await putState(input.kv, input.stateCodec, decoded.jobId, state).catch((stateError) => { + input.log.error({ + worker: input.logLabel, + jobId: decoded?.jobId, + error: toErrorMessage(stateError), + }, 'failed to persist failed state'); + }); + } + + if (hasRetriesLeft) { + msg.nak(); + input.log.error({ + worker: input.logLabel, + jobId: decoded?.jobId, + error: message, + deliveryCount, + maxAttempts: input.maxAttempts, + }, 'job failed, nacked for retry'); + } else { + msg.term(message); + input.log.error({ + worker: input.logLabel, + jobId: decoded?.jobId, + error: message, + deliveryCount, + maxAttempts: input.maxAttempts, + }, 'job failed, max attempts reached'); + } + } + } } async function main(): Promise { const port = readIntEnv('COMPUTE_WORKER_PORT', 8081); const host = process.env.COMPUTE_WORKER_HOST?.trim() || '0.0.0.0'; const workerToken = requireEnv('COMPUTE_WORKER_TOKEN'); - const redisUrl = requireEnv('REDIS_URL'); - const queueMaxDepth = readIntEnv('COMPUTE_QUEUE_MAX_DEPTH', 64); - const retryAfterSec = parseRetryAfterSeconds(process.env.COMPUTE_QUEUE_RETRY_AFTER_SEC); + const natsUrl = requireEnv('NATS_URL'); const whisperConcurrency = readIntEnv('COMPUTE_WHISPER_CONCURRENCY', 1); const pdfConcurrency = readIntEnv('COMPUTE_PDF_CONCURRENCY', 2); @@ -237,34 +412,15 @@ async function main(): Promise { const attempts = readIntEnv('COMPUTE_JOB_ATTEMPTS', 2); const prewarmModels = parseBoolEnv('COMPUTE_PREWARM_MODELS', true); - const redis = new IORedis(redisUrl, { - maxRetriesPerRequest: null, - enableReadyCheck: true, - }); + const nc: NatsConnection = await connect({ servers: natsUrl }); + const js: JetStreamClient = jetstream(nc); + const jsm: JetStreamManager = await jetstreamManager(nc); - const queueDefaults: JobsOptions = { - attempts, - backoff: { - type: 'exponential', - delay: 500, - }, - removeOnComplete: { - age: 60 * 60, - count: 1000, - }, - removeOnFail: { - age: 24 * 60 * 60, - count: 5000, - }, - }; + await ensureJetStreamResources(jsm, whisperTimeoutMs, pdfTimeoutMs, attempts); - const alignQueue = new Queue(ALIGN_QUEUE_NAME, { - connection: redis, - defaultJobOptions: queueDefaults, - }); - const layoutQueue = new Queue(PDF_LAYOUT_QUEUE_NAME, { - connection: redis, - defaultJobOptions: queueDefaults, + const kv = await new Kvm(js).create(JOB_STATES_BUCKET, { + history: 1, + ttl: JOB_STATES_TTL_MS, }); const s3 = buildS3Client(); @@ -289,123 +445,16 @@ async function main(): Promise { return toArrayBuffer(new Uint8Array(bytes)); }; - const alignWorker = new Worker( - ALIGN_QUEUE_NAME, - async (job) => { - const processingStartedAt = Date.now(); - const queueWaitMs = typeof job.timestamp === 'number' - ? Math.max(0, processingStartedAt - job.timestamp) - : undefined; - const parsed = alignSchema.parse(job.data); - const s3FetchStartedAt = Date.now(); - const audioBuffer = await readObjectByKey(parsed.audioObjectKey); - const s3FetchMs = Date.now() - s3FetchStartedAt; - const computeStartedAt = Date.now(); - const result = await withTimeout( - runWhisperAlignmentFromAudioBuffer({ - audioBuffer, - text: parsed.text, - cacheKey: parsed.cacheKey, - lang: parsed.lang, - }), - whisperTimeoutMs, - 'whisper alignment job', - ); - const computeMs = Date.now() - computeStartedAt; - return { - ...result, - timing: { - ...(result.timing ?? {}), - queueWaitMs, - s3FetchMs, - computeMs, - }, - }; - }, - { - connection: redis, - concurrency: whisperConcurrency, - }, - ); - - const layoutWorker = new Worker( - PDF_LAYOUT_QUEUE_NAME, - async (job) => { - const processingStartedAt = Date.now(); - const queueWaitMs = typeof job.timestamp === 'number' - ? Math.max(0, processingStartedAt - job.timestamp) - : undefined; - const parsed = layoutSchema.parse(job.data); - const s3FetchStartedAt = Date.now(); - const pdfBytes = await readObjectByKey(parsed.documentObjectKey); - const s3FetchMs = Date.now() - s3FetchStartedAt; - const computeStartedAt = Date.now(); - const result = await withTimeout( - runPdfLayoutFromPdfBuffer({ - documentId: parsed.documentId, - pdfBytes, - }), - pdfTimeoutMs, - 'pdf layout job', - ); - const computeMs = Date.now() - computeStartedAt; - return { - ...result, - timing: { - ...(result.timing ?? {}), - queueWaitMs, - s3FetchMs, - computeMs, - }, - }; - }, - { - connection: redis, - concurrency: pdfConcurrency, - }, - ); - if (prewarmModels) { await ensureComputeModels(); } - const app = Fastify({ - logger: buildLoggerConfig(), - }); + const app = Fastify({ logger: buildLoggerConfig() }); - alignWorker.on('completed', (job, result) => { - app.log.info({ - queue: ALIGN_QUEUE_NAME, - jobId: job.id, - timing: buildJobTimingSnapshot(job, readResultTiming(result)), - }, 'whisper align job completed'); - }); - - alignWorker.on('failed', (job, err) => { - app.log.error({ - queue: ALIGN_QUEUE_NAME, - jobId: job?.id, - error: err.message, - timing: job ? buildJobTimingSnapshot(job) : undefined, - }, 'whisper align job failed'); - }); - - layoutWorker.on('completed', (job, result) => { - app.log.info({ - queue: PDF_LAYOUT_QUEUE_NAME, - jobId: job.id, - timing: buildJobTimingSnapshot(job, readResultTiming(result)), - }, 'pdf layout job completed'); - }); - - layoutWorker.on('failed', (job, err) => { - app.log.error({ - queue: PDF_LAYOUT_QUEUE_NAME, - jobId: job?.id, - error: err.message, - timing: job ? buildJobTimingSnapshot(job) : undefined, - }, 'pdf layout job failed'); - }); + const whisperStateCodec = createJsonCodec>(); + const layoutStateCodec = createJsonCodec>(); + const whisperJobCodec = createJsonCodec>(); + const layoutJobCodec = createJsonCodec>(); app.addHook('onRequest', async (request, reply) => { const path = request.url.split('?')[0] ?? request.url; @@ -420,30 +469,17 @@ async function main(): Promise { app.get('/health/ready', async (_request, reply) => { try { - await redis.ping(); + await nc.flush(); return { ok: true }; } catch (error) { reply.code(503); return { ok: false, - error: error instanceof Error ? error.message : String(error), + error: toErrorMessage(error), }; } }); - const rejectIfSaturated = async (queue: Queue, reply: FastifyReply): Promise => { - const depth = await getQueueDepth(queue); - if (depth < queueMaxDepth) return false; - reply.header('Retry-After', String(retryAfterSec)); - reply.code(429).send({ - error: 'Queue is saturated', - retryAfterSeconds: retryAfterSec, - queueDepth: depth, - queueMaxDepth, - }); - return true; - }; - app.post('/align/whisper/jobs', async (request, reply) => { const parsed = alignSchema.safeParse(request.body); if (!parsed.success) { @@ -453,11 +489,24 @@ async function main(): Promise { issues: parsed.error.issues, }; } - if (await rejectIfSaturated(alignQueue, reply)) return; - const job = await alignQueue.add('align', parsed.data); + const jobId = crypto.randomUUID(); + const queuedAt = Date.now(); + + await putState(kv, whisperStateCodec, jobId, { + status: 'queued', + timestamp: queuedAt, + updatedAt: queuedAt, + }); + + await js.publish(WHISPER_JOBS_SUBJECT, whisperJobCodec.encode({ + jobId, + queuedAt, + payload: parsed.data, + })); + reply.code(202); - return { jobId: String(job.id) }; + return { jobId }; }); app.get('/align/whisper/jobs/:jobId', async (request, reply) => { @@ -466,12 +515,21 @@ async function main(): Promise { reply.code(400); return { error: 'Invalid job id' }; } - const job = await alignQueue.getJob(params.data.jobId); - if (!job) { + + const state = await getState(kv, whisperStateCodec, params.data.jobId); + if (!state) { reply.code(404); return { error: 'Job not found' }; } - return mapJobState(job); + + const response: WorkerJobStatusResponse = { + status: state.status, + ...(state.result ? { result: state.result } : {}), + ...(state.error ? { error: state.error } : {}), + ...(state.timing ? { timing: state.timing } : {}), + }; + + return response; }); app.post('/layout/pdf/jobs', async (request, reply) => { @@ -483,11 +541,24 @@ async function main(): Promise { issues: parsed.error.issues, }; } - if (await rejectIfSaturated(layoutQueue, reply)) return; - const job = await layoutQueue.add('layout', parsed.data); + const jobId = crypto.randomUUID(); + const queuedAt = Date.now(); + + await putState(kv, layoutStateCodec, jobId, { + status: 'queued', + timestamp: queuedAt, + updatedAt: queuedAt, + }); + + await js.publish(LAYOUT_JOBS_SUBJECT, layoutJobCodec.encode({ + jobId, + queuedAt, + payload: parsed.data, + })); + reply.code(202); - return { jobId: String(job.id) }; + return { jobId }; }); app.get('/layout/pdf/jobs/:jobId', async (request, reply) => { @@ -496,28 +567,136 @@ async function main(): Promise { reply.code(400); return { error: 'Invalid job id' }; } - const job = await layoutQueue.getJob(params.data.jobId); - if (!job) { + + const state = await getState(kv, layoutStateCodec, params.data.jobId); + if (!state) { reply.code(404); return { error: 'Job not found' }; } - return mapJobState(job); + + const response: WorkerJobStatusResponse = { + status: state.status, + ...(state.result ? { result: state.result } : {}), + ...(state.error ? { error: state.error } : {}), + ...(state.timing ? { timing: state.timing } : {}), + }; + + return response; }); + const whisperConsumer = await js.consumers.get(JOBS_STREAM_NAME, WHISPER_CONSUMER_NAME); + const layoutConsumer = await js.consumers.get(JOBS_STREAM_NAME, LAYOUT_CONSUMER_NAME); + + let stopping = false; + + const runWhisper = async ( + payload: WhisperAlignJobRequest, + queueWaitMs: number, + ): Promise => { + const parsed = alignSchema.parse(payload); + + const s3FetchStartedAt = Date.now(); + const audioBuffer = await readObjectByKey(parsed.audioObjectKey); + const s3FetchMs = Date.now() - s3FetchStartedAt; + + const computeStartedAt = Date.now(); + const result = await withTimeout( + runWhisperAlignmentFromAudioBuffer({ + audioBuffer, + text: parsed.text, + cacheKey: parsed.cacheKey, + lang: parsed.lang, + }), + whisperTimeoutMs, + 'whisper alignment job', + ); + + const computeMs = Date.now() - computeStartedAt; + return { + ...result, + timing: { + ...(result.timing ?? {}), + queueWaitMs, + s3FetchMs, + computeMs, + }, + }; + }; + + const runLayout = async ( + payload: PdfLayoutJobRequest, + queueWaitMs: number, + ): Promise => { + const parsed = layoutSchema.parse(payload); + + const s3FetchStartedAt = Date.now(); + const pdfBytes = await readObjectByKey(parsed.documentObjectKey); + const s3FetchMs = Date.now() - s3FetchStartedAt; + + const computeStartedAt = Date.now(); + const result = await withTimeout( + runPdfLayoutFromPdfBuffer({ + documentId: parsed.documentId, + pdfBytes, + }), + pdfTimeoutMs, + 'pdf layout job', + ); + + const computeMs = Date.now() - computeStartedAt; + return { + ...result, + timing: { + ...(result.timing ?? {}), + queueWaitMs, + s3FetchMs, + computeMs, + }, + }; + }; + + const workerLoops: Promise[] = []; + + for (let i = 0; i < whisperConcurrency; i += 1) { + workerLoops.push(createWorkerLoop({ + consumer: whisperConsumer, + kv, + stateCodec: whisperStateCodec, + jobCodec: whisperJobCodec, + run: runWhisper, + maxAttempts: attempts, + logLabel: `whisper-${i + 1}`, + shouldStop: () => stopping, + log: app.log, + })); + } + + for (let i = 0; i < pdfConcurrency; i += 1) { + workerLoops.push(createWorkerLoop({ + consumer: layoutConsumer, + kv, + stateCodec: layoutStateCodec, + jobCodec: layoutJobCodec, + run: runLayout, + maxAttempts: attempts, + logLabel: `layout-${i + 1}`, + shouldStop: () => stopping, + log: app.log, + })); + } + const close = async (): Promise => { + if (stopping) return; + stopping = true; await app.close(); - await Promise.allSettled([ - alignWorker.close(), - layoutWorker.close(), - alignQueue.close(), - layoutQueue.close(), - redis.quit(), - ]); + await Promise.allSettled(workerLoops); + await nc.drain(); }; process.once('SIGINT', () => { void close().finally(() => process.exit(0)); }); + process.once('SIGTERM', () => { void close().finally(() => process.exit(0)); }); diff --git a/docs-site/docs/deploy/compute-worker.md b/docs-site/docs/deploy/compute-worker.md index af00ab2..f57ce9a 100644 --- a/docs-site/docs/deploy/compute-worker.md +++ b/docs-site/docs/deploy/compute-worker.md @@ -1,5 +1,4 @@ ---- -title: Compute Worker (Redis + BullMQ) +title: Compute Worker (NATS JetStream) --- Use this guide for `COMPUTE_MODE=worker` deployments where heavy compute runs outside the Next.js app server. @@ -11,7 +10,7 @@ The compute worker handles: - Whisper word alignment (`/align/whisper/jobs`) - PDF layout parsing (`/layout/pdf/jobs`) -The app server enqueues jobs and polls status. Queue durability and retries are backed by Redis + BullMQ. +The app server enqueues jobs and polls status. Queue durability and retries are backed by NATS JetStream WorkQueue consumers and NATS KV. ## Published image @@ -23,7 +22,7 @@ The app server enqueues jobs and polls status. Queue durability and retries are Required: - `COMPUTE_WORKER_TOKEN`: bearer token expected by worker routes -- `REDIS_URL`: BullMQ Redis connection string +- `NATS_URL`: NATS server connection string (JetStream enabled) - `S3_BUCKET` - `S3_REGION` - `S3_ACCESS_KEY_ID` @@ -37,7 +36,6 @@ Common optional: - `COMPUTE_WORKER_HOST=0.0.0.0` - `COMPUTE_WORKER_PORT=8081` - `COMPUTE_LOG_FORMAT=pretty` (default) or `json` -- `COMPUTE_QUEUE_MAX_DEPTH=64` - `COMPUTE_PREWARM_MODELS=true` ## App server environment variables (worker mode) diff --git a/docs-site/docs/deploy/local-development.md b/docs-site/docs/deploy/local-development.md index 80c07c7..22703cf 100644 --- a/docs-site/docs/deploy/local-development.md +++ b/docs-site/docs/deploy/local-development.md @@ -127,10 +127,10 @@ If you need mirrors or pinned artifact locations, set `WHISPER_MODEL_BASE_URL` i
External compute worker dev stack (optional) -Use this when you want durable compute with Redis/BullMQ while keeping Next.js on native host `pnpm dev`. -Full worker deployment details are in [Compute Worker (Redis + BullMQ)](./compute-worker). +Use this when you want durable compute with NATS JetStream + KV while keeping Next.js on native host `pnpm dev`. +Full worker deployment details are in [Compute Worker (NATS JetStream)](./compute-worker). -Start only Redis + compute-worker via compose watch: +Start only NATS + compute-worker via compose watch: ```bash docker compose --env-file compute/worker/.env -f compute/worker/docker-compose.yml up --watch @@ -243,7 +243,7 @@ S3_SECRET_ACCESS_KEY=your-secret-key ``` - + ```env API_BASE=http://host.docker.internal:8880/v1 diff --git a/docs-site/docs/deploy/vercel-deployment.md b/docs-site/docs/deploy/vercel-deployment.md index 3c1502b..7fa3842 100644 --- a/docs-site/docs/deploy/vercel-deployment.md +++ b/docs-site/docs/deploy/vercel-deployment.md @@ -9,7 +9,7 @@ This guide covers deploying OpenReader to Vercel with external Postgres and S3-c - Documents (PDF/EPUB/TXT/MD) work with `POSTGRES_URL` + external S3 storage. - Audiobook routes work on Node.js serverless functions using `ffmpeg-static`. - Heavy compute features (Whisper alignment + PDF layout parsing) work through `COMPUTE_MODE=worker` with an external compute worker service. -- For worker setup details and worker-specific env vars, see [Compute Worker (Redis + BullMQ)](./compute-worker). +- For worker setup details and worker-specific env vars, see [Compute Worker (NATS JetStream)](./compute-worker). :::warning DOCX Conversion Limitation `docx` conversion requires `soffice` (LibreOffice), which is not available in a standard Vercel runtime. diff --git a/docs-site/docs/docker-quick-start.md b/docs-site/docs/docker-quick-start.md index 97a555a..f61ea07 100644 --- a/docs-site/docs/docker-quick-start.md +++ b/docs-site/docs/docker-quick-start.md @@ -141,7 +141,7 @@ Visit [http://localhost:3003](http://localhost:3003) after startup. ## 3. Update Docker image Legacy image compatibility: `ghcr.io/richardr1126/openreader-webui:latest` remains available as an alias. -For external compute mode image details, see [Compute Worker (Redis + BullMQ)](./deploy/compute-worker). +For external compute mode image details, see [Compute Worker (NATS JetStream)](./deploy/compute-worker). ```bash docker stop openreader || true && \ diff --git a/docs-site/docs/introduction.md b/docs-site/docs/introduction.md index d8c3c67..4759768 100644 --- a/docs-site/docs/introduction.md +++ b/docs-site/docs/introduction.md @@ -15,7 +15,7 @@ It supports multiple TTS providers including OpenAI, Replicate, DeepInfra, and c - 🧱 **Layout-aware PDF Parsing** - PP-DocLayoutV3 (ONNX) detects structured blocks with cross-page stitching and geometry-based highlighting for precise read-along sync and clean TTS segmentation - ⏱️ **Word-by-word Highlighting** via ONNX Whisper alignment - - No external dependencies — runs in-process (`COMPUTE_MODE=local`) or offloaded to a scalable Redis-backed worker (`COMPUTE_MODE=worker`) + - No external dependencies — runs in-process (`COMPUTE_MODE=local`) or offloaded to a scalable NATS JetStream-backed worker (`COMPUTE_MODE=worker`) - ⚡ **Segment-based TTS Playback** - Sentence-aware generation with cached audio segments, background preloading, and resumable playback across EPUB, PDF, TXT, MD, and DOCX - 🎯 **Multi-Provider TTS Support** diff --git a/docs-site/docs/reference/environment-variables.md b/docs-site/docs/reference/environment-variables.md index 207b30a..efae35e 100644 --- a/docs-site/docs/reference/environment-variables.md +++ b/docs-site/docs/reference/environment-variables.md @@ -357,11 +357,11 @@ Selects the backend for heavy compute features (ONNX word alignment + PDF layout - Default: `local` - Supported in v1: - `local`: run compute in-process on the app server - - `worker`: enqueue async jobs in an external durable compute worker (Redis + BullMQ) + - `worker`: enqueue async jobs in an external durable compute worker (NATS JetStream + NATS KV) - `worker` requires `COMPUTE_WORKER_URL` and `COMPUTE_WORKER_TOKEN` - `worker` assumes the external worker can directly reach shared object storage (S3-compatible endpoint) - `worker` is not compatible with non-exposed embedded `weed mini` storage topologies -- Worker service env vars are documented in [Compute Worker (Redis + BullMQ)](../deploy/compute-worker) +- Worker service env vars are documented in [Compute Worker (NATS JetStream)](../deploy/compute-worker) ### COMPUTE_WORKER_URL diff --git a/docs-site/docs/reference/stack.md b/docs-site/docs/reference/stack.md index 7f4061a..5d1d538 100644 --- a/docs-site/docs/reference/stack.md +++ b/docs-site/docs/reference/stack.md @@ -55,11 +55,11 @@ Monorepo packages under `compute/`: - Utilities: `jszip`, `ffmpeg-static` - **`@openreader/compute-worker`** — standalone Node.js worker service - HTTP server: [Fastify](https://fastify.dev/) v5 - - Job queue: [BullMQ](https://bullmq.io/) + [ioredis](https://github.com/redis/ioredis) (queues: `whisper-align`, `pdf-layout`) + - Job queue + state: [NATS](https://nats.io/) JetStream WorkQueue pull consumers + NATS KV (`jobs.whisper`, `jobs.layout`) - Storage: AWS SDK v3 S3 client for reading/writing blobs - Logging: [Pino](https://getpino.io/) - Validation: [Zod](https://zod.dev/) -- Compute mode is controlled by `COMPUTE_MODE` env var: `local` (in-process) or `worker` (remote queue via HTTP + Redis) +- Compute mode is controlled by `COMPUTE_MODE` env var: `local` (in-process) or `worker` (remote queue via HTTP + NATS) ## Tooling and testing diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 49947fd..7303f48 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -148,7 +148,7 @@ importers: version: 1.60.0 '@tailwindcss/typography': specifier: ^0.5.19 - version: 0.5.19(tailwindcss@3.4.19(tsx@4.21.0)) + version: 0.5.19(tailwindcss@3.4.19(tsx@4.22.3)) '@types/better-sqlite3': specifier: ^7.6.13 version: 7.6.13 @@ -181,7 +181,7 @@ importers: version: 8.5.14 tailwindcss: specifier: ^3.4.19 - version: 3.4.19(tsx@4.21.0) + version: 3.4.19(tsx@4.22.3) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -210,23 +210,26 @@ importers: compute/worker: dependencies: '@aws-sdk/client-s3': - specifier: ^3.1045.0 - version: 3.1045.0 + specifier: ^3.1050.0 + version: 3.1050.0 + '@nats-io/jetstream': + specifier: ^3.4.0 + version: 3.4.0 + '@nats-io/kv': + specifier: ^3.4.0 + version: 3.4.0 + '@nats-io/transport-node': + specifier: ^3.4.0 + version: 3.4.0 '@openreader/compute-core': specifier: workspace:* version: link:../core - bullmq: - specifier: ^5.61.2 - version: 5.76.10 fastify: specifier: ^5.6.2 version: 5.8.5 - ioredis: - specifier: ^5.8.2 - version: 5.10.1 pino: - specifier: ^9.14.0 - version: 9.14.0 + specifier: ^10.3.1 + version: 10.3.1 pino-pretty: specifier: ^13.1.2 version: 13.1.3 @@ -235,8 +238,8 @@ importers: version: 4.4.3 devDependencies: tsx: - specifier: ^4.20.6 - version: 4.21.0 + specifier: ^4.22.3 + version: 4.22.3 packages: @@ -271,6 +274,14 @@ packages: resolution: {integrity: sha512-fsuO3Y6t+3Ro9Bsg41DKj4Sfy53CGSrhnMldNplWmG8Tx0UbYk+YDa4RD1hVlJpERw4JBmPkl0+J9qlxMh1pcA==} engines: {node: '>=20.0.0'} + '@aws-sdk/client-s3@3.1050.0': + resolution: {integrity: sha512-9kgtv+bXZQrOIJT2INPPBCezrJu1FlgGrzEat/ut4A4V53IT00LynsBZgp12eFKbjJuNCeTo7iPSKjPsX8ub+A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/core@3.974.12': + resolution: {integrity: sha512-qrqgioqYFjwR6LatVNS1L2Vk++EwRIxqSQXPKNv5Ofux2D8UNgqMQ1znnMyEImXquVPTtbf71fc128pvmU6y9A==} + engines: {node: '>=20.0.0'} + '@aws-sdk/core@3.974.8': resolution: {integrity: sha512-njR2qoG6ZuB0kvAS2FyICsFZJ6gmCcf2X/7JcD14sUvGDm26wiZ5BrA6LOiUxKFEF+IVe7kdroxyE00YlkiYsw==} engines: {node: '>=20.0.0'} @@ -279,50 +290,98 @@ packages: resolution: {integrity: sha512-QUagVVBbC8gODCF6e1aV0mE2TXWB9Opz4k8EJFdNrujUVQm5R4AjJa1mpOqzwOuROBzqJU9zawzig7M96L8Ejg==} engines: {node: '>=20.0.0'} + '@aws-sdk/crc64-nvme@3.972.8': + resolution: {integrity: sha512-fVfUCL/Xh2zINYMPZvj+iBn6XWouQf0DAnjaWCI9MkmqXzL2Iy5FoQB8O7syFe6gN6AH1ecDDU58T51Ou0kFkA==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-env@3.972.34': resolution: {integrity: sha512-XT0jtf8Fw9JE6ppsQeoNnZRiG+jqRixMT1v1ZR17G60UvVdsQmTG8nbEyHuEPfMxDXEhfdARaM/XiEhca4lGHQ==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-env@3.972.38': + resolution: {integrity: sha512-m3WjZEgPtioMhPmwqUt+DhlTJ2i9ufR6DhfkyXojb9puEvfR+ur2U5shavu5/Cc9WHHsDCvALi6UFHgcqjhQ5w==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-http@3.972.36': resolution: {integrity: sha512-DPoGWfy7J7RKxvbf5kOKIGQkD2ek3dbKgzKIGrnLuvZBz5myU+Im/H6pmc14QcnFbqHMqxvtWSgRDSJW3qXLQg==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-http@3.972.40': + resolution: {integrity: sha512-D78L/m2Dr6cJnnSvWoAudPhQmCwmJ7j6APXsPYmFpPaKfQTfCSu0rdm8j14Np+VmXF9z8Aj8HE3xFpsrwtfgeg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-ini@3.972.38': resolution: {integrity: sha512-oDzUBu2MGJFgoar05sPMCwSrhw44ASyccrHzj66vO69OZqi7I6hZZxXfuPLC8OCzW7C+sU+bI73XHij41yekgQ==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-ini@3.972.42': + resolution: {integrity: sha512-Mu5ESvFXeinafVM8jTIvRqcvK2Ehj4kz3auT39yUcHwu1Vfxo6xRlmUafdKLW4tusjAJukQwK09sCSMgOm7OKg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-login@3.972.38': resolution: {integrity: sha512-g1NosS8qe4OF++G2UFCM5ovSkgipC7YYor5KCWatG0UoMSO5YFj9C8muePlyVmOBV/WTI16Jo3/s1NUo/o1Bww==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-login@3.972.42': + resolution: {integrity: sha512-O6WkZga3kf0yqyJYd1dbeJqVhEgJx/x1UaLgtbR+XuL/YP+K5y6QTxQKL7ka9z3jnQASESKGAPnRyt4D5hQrxA==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-node@3.972.39': resolution: {integrity: sha512-HEswDQyxUtadoZ/bJsPPENHg7R0Lzym5LuMksJeHvqhCOpP+rtkDLKI4/ZChH4w3cf5kG8n6bZuI8PzajoiqMg==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-node@3.972.43': + resolution: {integrity: sha512-D/DJmbrWRP5BXEO3FH+ar4el+2n6OlGofiud7dQun2jES+AQEJjczenp1jBb4MBN7CpGpS8nsWGQLtuzc9tQbA==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-process@3.972.34': resolution: {integrity: sha512-T3IFs4EVmVi1dVN5RciFnklCANSzvrQd/VuHY9ThHSQmYkTogjcGkoJEr+oNUPQZnso52183088NqysMPji1/Q==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-process@3.972.38': + resolution: {integrity: sha512-EnbYVajGgbkb24s0K1eo4VNAPV5mHIET7LSvirTaFCwkfrfaOJxtSE+wY/tJdKDS21cEYkZs2ruCaAm+W4iblg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-sso@3.972.38': resolution: {integrity: sha512-5ZxG+t0+3Q3QPh8KEjX6syskhgNf7I0MN7oGioTf6Lm1NTjfP7sIcYGNsthXC2qR8vcD3edNZwCr2ovfSSWuRA==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-sso@3.972.42': + resolution: {integrity: sha512-RVV/9NbFwI8ZHEH5dn39lGyFmSbSVj1+orZdr6QsOe1mW9DCglmlen0cFaNZmCcqkqc7erNRHNBduxbeZuHAnw==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-web-identity@3.972.38': resolution: {integrity: sha512-lYHFF30DGI20jZcYX8cm6Ns0V7f1dDN6g/MBDLTyD/5iw+bXs3yBr2iAiHDkx4RFU5JgsnZvCHYKiRVPRdmOgw==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-web-identity@3.972.42': + resolution: {integrity: sha512-/67fXX0ddllD4u2Nujc5PvT4byHgpMUfz6+RxIKi/0nFIckeorm7JvXgzBuDyVKw0s58EbofmETDWUf9vTEuHQ==} + engines: {node: '>=20.0.0'} + '@aws-sdk/middleware-bucket-endpoint@3.972.10': resolution: {integrity: sha512-Vbc2frZH7wXlMNd+ZZSXUEs/l1Sv8Jj4zUnIfwrYF5lwaLdXHZ9xx4U3rjUcaye3HRhFVc+E5DbBxpRAbB16BA==} engines: {node: '>=20.0.0'} + '@aws-sdk/middleware-bucket-endpoint@3.972.14': + resolution: {integrity: sha512-Aaj0d+xbo1jJquBWJP0/9V/XZRYukO3LWIRp3dOLHmoFrYKb4YZ0aLefgVHfGcNOVBS2ZTq7L/n5JcrE7DaC+Q==} + engines: {node: '>=20.0.0'} + '@aws-sdk/middleware-expect-continue@3.972.10': resolution: {integrity: sha512-2Yn0f1Qiq/DjxYR3wfI3LokXnjOhFM7Ssn4LTdFDIxRMCE6I32MAsVnhPX1cUZsuVA9tiZtwwhlSLAtFGxAZlQ==} engines: {node: '>=20.0.0'} + '@aws-sdk/middleware-expect-continue@3.972.12': + resolution: {integrity: sha512-dA5pKTom/Ls9mgeyeaRBNQrRIVOLVjv4AmKOB0/e4yaiXEUy0gSz2d3liP8JHtYoCAEWySU1jWnyzwLOREN+4g==} + engines: {node: '>=20.0.0'} + '@aws-sdk/middleware-flexible-checksums@3.974.16': resolution: {integrity: sha512-6ru8doI0/XzszqLIPXf0E/V7HhAw1Pu94010XCKYtBUfD0LxF0BuOzrUf8OQGR6j2o6wgKTHUniOmndQycHwCA==} engines: {node: '>=20.0.0'} + '@aws-sdk/middleware-flexible-checksums@3.974.20': + resolution: {integrity: sha512-NdnMVQCR1YjIcqFAiNLdBiOwr2DyQDB2IiXQrBhzolKOv32ae4d4Ll7IzLMi04eMHiq/o/Y/GjFuVjF9HuG0QA==} + engines: {node: '>=20.0.0'} + '@aws-sdk/middleware-host-header@3.972.10': resolution: {integrity: sha512-IJSsIMeVQ8MMCPbuh1AbltkFhLBLXn7aejzfX5YKT/VLDHn++Dcz8886tXckE+wQssyPUhaXrJhdakO2VilRhg==} engines: {node: '>=20.0.0'} @@ -343,6 +402,10 @@ packages: resolution: {integrity: sha512-Km7M+i8DrLArVzrid1gfxeGhYHBd3uxvE77g0s5a52zPSVosxzQBnJ0gwWb6NIp/DOk8gsBMhi7V+cpJG0ndTA==} engines: {node: '>=20.0.0'} + '@aws-sdk/middleware-sdk-s3@3.972.41': + resolution: {integrity: sha512-M4T2I2WPuH5WQpU8Tsp+u2bcO29zGRkU14ATzuqb9I4xh8tzsLqtp4hzaJM5aO2dhMZnHDzyQwSFVgc3XbnoGg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/middleware-ssec@3.972.10': resolution: {integrity: sha512-Gli9A0u8EVVb+5bFDGS/QbSVg28w/wpEidg1ggVcSj65BDTdGR6punsOcVjqdiu1i42WHWo51MCvARPIIz9juw==} engines: {node: '>=20.0.0'} @@ -351,6 +414,10 @@ packages: resolution: {integrity: sha512-iz+B29TXcAZsJpwB+AwG/TTGA5l/VnmMZ2UxtiySOZjI6gCdmviXPwdgzcmuazMy16rXoPY4mYCGe7zdNKfx5A==} engines: {node: '>=20.0.0'} + '@aws-sdk/nested-clients@3.997.10': + resolution: {integrity: sha512-FtQ/Bt327peZJuyo4WZSOLVUTw9ujRxntepiC7L65FxA2P82Xlq0g14T22BuqBUeMjDoxa9nvwiMHjLIfP3eUg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/nested-clients@3.997.6': resolution: {integrity: sha512-WBDnqatJl+kGObpfmfSxqnXeYTu3Me8wx8WCtvoxX3pfWrrTv8I4WTMSSs7PZqcRcVh8WeUKMgGFjMG+52SR1w==} engines: {node: '>=20.0.0'} @@ -367,10 +434,18 @@ packages: resolution: {integrity: sha512-+CMIt3e1VzlklAECmG+DtP1sV8iKq25FuA0OKpnJ4KA0kxUtd7CgClY7/RU6VzJBQwbN4EJ9Ue6plvqx1qGadw==} engines: {node: '>=20.0.0'} + '@aws-sdk/signature-v4-multi-region@3.996.27': + resolution: {integrity: sha512-0Phbz4t6HI3D3skxvG2uI+VWU034/nSIw1T8d+FPzzQG9EQTrw94o9mOKO2Gv3n3Oc8P7JD7RAUxkoneLWv5Eg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/token-providers@3.1041.0': resolution: {integrity: sha512-Th7kPI6YPtvJUcdznooXJMy+9rQWjmEF81LxaJssngBzuysK4a/x+l8kjm1zb7nYsUPbndnBdUnwng/3PLvtGw==} engines: {node: '>=20.0.0'} + '@aws-sdk/token-providers@3.1049.0': + resolution: {integrity: sha512-r7+d0lQMTHKypkmaF5jRTBYLYHCUHzt3gaVoN9SidLhQeWhCmHk3AKrboDTpPF5b7Pt7vKu3+oeMjznM2Eu1ow==} + engines: {node: '>=20.0.0'} + '@aws-sdk/types@3.973.8': resolution: {integrity: sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw==} engines: {node: '>=20.0.0'} @@ -407,6 +482,10 @@ packages: resolution: {integrity: sha512-PMYKKtJd70IsSG0yHrdAbxBr+ZWBKLvzFZfD3/urxgf6hXVMzuU5M+3MJ5G67RpOmLBu1fAUN65SbWuKUCOlAA==} engines: {node: '>=20.0.0'} + '@aws-sdk/xml-builder@3.972.24': + resolution: {integrity: sha512-V8z5YcDPfsvzrBlj0xR1vhRtocblhYbqdreCJB/voGd4Sr5zjNAeWxexbnqVtskTJe0vFb5KMqbSL++ePl+zRw==} + engines: {node: '>=20.0.0'} + '@aws/lambda-invoke-store@0.2.4': resolution: {integrity: sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==} engines: {node: '>=18.0.0'} @@ -530,6 +609,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.28.0': + resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.18.20': resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} engines: {node: '>=12'} @@ -548,6 +633,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.28.0': + resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.18.20': resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} engines: {node: '>=12'} @@ -566,6 +657,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.28.0': + resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.18.20': resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} engines: {node: '>=12'} @@ -584,6 +681,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.28.0': + resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.18.20': resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} engines: {node: '>=12'} @@ -602,6 +705,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.28.0': + resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.18.20': resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} engines: {node: '>=12'} @@ -620,6 +729,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.28.0': + resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.18.20': resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} engines: {node: '>=12'} @@ -638,6 +753,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.28.0': + resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.18.20': resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} engines: {node: '>=12'} @@ -656,6 +777,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.28.0': + resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.18.20': resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} engines: {node: '>=12'} @@ -674,6 +801,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.28.0': + resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.18.20': resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} engines: {node: '>=12'} @@ -692,6 +825,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.28.0': + resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.18.20': resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} engines: {node: '>=12'} @@ -710,6 +849,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.28.0': + resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.18.20': resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} engines: {node: '>=12'} @@ -728,6 +873,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.28.0': + resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.18.20': resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} engines: {node: '>=12'} @@ -746,6 +897,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.28.0': + resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.18.20': resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} engines: {node: '>=12'} @@ -764,6 +921,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.28.0': + resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.18.20': resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} engines: {node: '>=12'} @@ -782,6 +945,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.28.0': + resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.18.20': resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} engines: {node: '>=12'} @@ -800,6 +969,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.28.0': + resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.18.20': resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} engines: {node: '>=12'} @@ -818,6 +993,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.28.0': + resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-arm64@0.25.12': resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} engines: {node: '>=18'} @@ -830,6 +1011,12 @@ packages: cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-arm64@0.28.0': + resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.18.20': resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} engines: {node: '>=12'} @@ -848,6 +1035,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.28.0': + resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.25.12': resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} @@ -860,6 +1053,12 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.28.0': + resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.18.20': resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} engines: {node: '>=12'} @@ -878,6 +1077,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.28.0': + resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openharmony-arm64@0.25.12': resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} engines: {node: '>=18'} @@ -890,6 +1095,12 @@ packages: cpu: [arm64] os: [openharmony] + '@esbuild/openharmony-arm64@0.28.0': + resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/sunos-x64@0.18.20': resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} engines: {node: '>=12'} @@ -908,6 +1119,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.28.0': + resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.18.20': resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} engines: {node: '>=12'} @@ -926,6 +1143,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.28.0': + resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.18.20': resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} engines: {node: '>=12'} @@ -944,6 +1167,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.28.0': + resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.18.20': resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} engines: {node: '>=12'} @@ -962,6 +1191,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.28.0': + resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.9.1': resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1231,9 +1466,6 @@ packages: '@internationalized/string@3.2.8': resolution: {integrity: sha512-NdbMQUSfXLYIQol5VyMtinm9pZDciiMfN7RtmSuSB78io1hqwJ0naYfxyW6vgxWBkzWymQa/3uLDlbfmshtCaA==} - '@ioredis/commands@1.5.1': - resolution: {integrity: sha512-JH8ZL/ywcJyR9MmJ5BNqZllXNZQqQbnVZOqpPQqE1vHiFgAw4NHbvE0FOduNU8IX9babitBT46571OnPTT0Zcw==} - '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -1251,36 +1483,6 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': - resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==} - cpu: [arm64] - os: [darwin] - - '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': - resolution: {integrity: sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==} - cpu: [x64] - os: [darwin] - - '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': - resolution: {integrity: sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==} - cpu: [arm64] - os: [linux] - - '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': - resolution: {integrity: sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==} - cpu: [arm] - os: [linux] - - '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': - resolution: {integrity: sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==} - cpu: [x64] - os: [linux] - - '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': - resolution: {integrity: sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==} - cpu: [x64] - os: [win32] - '@napi-rs/canvas-android-arm64@0.1.100': resolution: {integrity: sha512-hjhCKhntPv9+t4ckHymdx0phYNcVW+GKQR6Lzw2zE+pOVjOplSmtx9nNNknTjbEDLcuLZqA1y8ufKg1XfgftzQ==} engines: {node: '>= 10'} @@ -1359,6 +1561,27 @@ packages: '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + '@nats-io/jetstream@3.4.0': + resolution: {integrity: sha512-GzHQodNJ942+R5LRb8PuZ5ugVWVWMRiufxUYLLVWkXKfwDXYN+Owo0d7L/b9O7BPyrbYD7jQWAC6+ZVuXa9Gyw==} + + '@nats-io/kv@3.4.0': + resolution: {integrity: sha512-168pcRJxWcIRHwdyczI3DaGk5r3CAj3CyKXuk4Nmx5KKj7N1znQOJPIxCoV0TPlAvoTidVb7eBv41J9imapMeQ==} + + '@nats-io/nats-core@3.4.0': + resolution: {integrity: sha512-QMDM86EUNm+wudlKC67HLar/KHHQUvJGLfb4jbahje3pUk3K9afeck9fwsxBZF0eUFox6T/TA6m/t+lQqf+QsQ==} + + '@nats-io/nkeys@2.0.3': + resolution: {integrity: sha512-JVt56GuE6Z89KUkI4TXUbSI9fmIfAmk6PMPknijmuL72GcD+UgIomTcRWiNvvJKxA01sBbmIPStqJs5cMRBC3A==} + engines: {node: '>=18.0.0'} + + '@nats-io/nuid@3.0.0': + resolution: {integrity: sha512-QbXZDrxmYlrn5AD06gYcUTmEHwxn96HBQMIk7XTjDlEcx6FPzVBBPjp4AMRh1lEv6B4iJ6Xb/Uz61JugPXFRQg==} + engines: {node: '>= 22.x'} + + '@nats-io/transport-node@3.4.0': + resolution: {integrity: sha512-hH7u7ejIBTFEJIZ8rIcMrHJI6wl+HhpO5sVFs1+ppmXa8RuB2+Lh1+UwTzZ5xTNNm1TKcRkYy+2qCV56qp8RxA==} + engines: {node: '>= 18.0.0'} + '@next/env@15.5.18': resolution: {integrity: sha512-hAV85Ckd9QR6RvH04MEKwsfLTksvFpO47j9xwtoIuvuPnlwecpSi+uZTtm8HirVbtlI2Fnz//xpcSTjFdyJk+g==} @@ -1501,10 +1724,18 @@ packages: engines: {node: '>=18.0.0'} deprecated: Deprecated due to bug in browser bundling instructions https://github.com/smithy-lang/smithy-typescript/issues/2025 + '@smithy/core@3.24.3': + resolution: {integrity: sha512-Ep/7tPamGY8mgESE3LyLKtxJyy6U52WWAqr/3wial47Sj4u3PiIF73AOGI27UyLy9duTkhZbgzodOfLV4TduZg==} + engines: {node: '>=18.0.0'} + '@smithy/credential-provider-imds@4.3.1': resolution: {integrity: sha512-0S/acwHnqX4WrjXzhdiDRxsG2s9SC0cpPIK9nZ1R6UOHd+j7uL28+4bHu22urbLk2TVw3fkp6na/+fkUt/pLNQ==} engines: {node: '>=18.0.0'} + '@smithy/credential-provider-imds@4.3.3': + resolution: {integrity: sha512-I2Bti0DKFo2IJyN28ijCsx51BAumEYR4/1yZ1FXyBygy9MqbnMqCev4JPth/MbpRfBSRAX35hITSnAdJRo1u5w==} + engines: {node: '>=18.0.0'} + '@smithy/eventstream-serde-browser@4.3.1': resolution: {integrity: sha512-X7MyI1fu8M84IPKk49kO4kb27Mqp6un9/0o/MsA1ngZ5OxxWKGUxPS3S/AJ9q1cPVTSGmRcbaGNfGUSsflTJkg==} engines: {node: '>=18.0.0'} @@ -1521,6 +1752,10 @@ packages: resolution: {integrity: sha512-r7bN6spQ+caZC8AnyvSxkRUb57zt2jhhRw3Z+2Ez8hjq6coIikDBFUUI/+CQ1xx9K6eX1Gx6wUKo4ylU66TIqw==} engines: {node: '>=18.0.0'} + '@smithy/fetch-http-handler@5.4.3': + resolution: {integrity: sha512-F+DRf8IJazRJgYog2A/yJK7eYVc0rqTlRzO+5ZxjJd4WkZoKz0IJRncf7G6t1pdVT3kryJcwuTFhN1c5m6N47A==} + engines: {node: '>=18.0.0'} + '@smithy/hash-blob-browser@4.3.1': resolution: {integrity: sha512-2fbltQVQYmGd0OzPv2oDMRF0pxkzeIx8cbpx2x6W3UJWGaEyUzVPxF4d0sDXZ/r2obg+RbTyhTidXWlPDsKRKw==} engines: {node: '>=18.0.0'} @@ -1577,6 +1812,10 @@ packages: resolution: {integrity: sha512-BdEYko85f/ldp68uH8XEyIvo810xFk6eyPH81SRggTOApYHWA+Xu7B2EzLuHbe37WVLaUA7F1fWR3/zBeme2WA==} engines: {node: '>=18.0.0'} + '@smithy/node-http-handler@4.7.3': + resolution: {integrity: sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA==} + engines: {node: '>=18.0.0'} + '@smithy/property-provider@4.3.1': resolution: {integrity: sha512-3NHoqVBhzpY2b4YBx9AqyKC4C8nnEjl5FyKuxrCjvnjinG0ODj+yg1xX360nNahT6wghYjSw1SooCt3kIdnqIA==} engines: {node: '>=18.0.0'} @@ -1597,6 +1836,10 @@ packages: resolution: {integrity: sha512-728lZZEWYWubBESrfntNslZQYDKRlJDY4dcDnYbL50+gu35pGPLblu4S0/RH/RDLF6me1M87ECHsHELGL7dA/Q==} engines: {node: '>=18.0.0'} + '@smithy/signature-v4@5.4.3': + resolution: {integrity: sha512-53+75QuPl6DL+ct6vVEB51FDO5oulXr20TPV46VvJZg76lIlXNWfxi8j+G2V/t0I2qxCBOa3vX/8bmjrpFVo9g==} + engines: {node: '>=18.0.0'} + '@smithy/smithy-client@4.13.1': resolution: {integrity: sha512-IcznNM8Qd9u1X3oflp12tkzyOB4HbT+sfYWlWiyEysgNzSHoWcHUUsTT4y1jjDjtVuuVVQbYks+g1kVd7u1eGQ==} engines: {node: '>=18.0.0'} @@ -1605,6 +1848,10 @@ packages: resolution: {integrity: sha512-59b5HtSVrVR/eYNei3BUj3DCPKD/G7EtDDe7OEJE7i7FtQFugYo6MxbotS8mVJkLNVf8gYaAlEBwwtJ9HzhWSg==} engines: {node: '>=18.0.0'} + '@smithy/types@4.14.2': + resolution: {integrity: sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw==} + engines: {node: '>=18.0.0'} + '@smithy/url-parser@4.3.1': resolution: {integrity: sha512-tuelFlF2PZR/wogFC58NIrPOv+Zna4N1+3kA161/33D1Gbwvl6Nh4WsAsW05ZyPp0O6CMGsdbb0S2b/qVjRMCw==} engines: {node: '>=18.0.0'} @@ -2281,10 +2528,6 @@ packages: buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - bullmq@5.76.10: - resolution: {integrity: sha512-LWve7SpQjYSpCP2GEsWmoyzTz2H37L8HRmSTu3YihYsTOr5kJxrfEX6aEV7m6eskEMWXSHZYTMZepX6qNaH6CQ==} - engines: {node: '>=12.22.0'} - call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -2348,10 +2591,6 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} - cluster-key-slot@1.1.2: - resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} - engines: {node: '>=0.10.0'} - cmpstr@3.3.0: resolution: {integrity: sha512-of06NSLK24YPV89qYmlJQxENZF43BtIGlXmrFaUIdkuBMayIckFX9NjRB6PPfkhxpLIOb6LhiTe/P5QoBu6r3w==} engines: {node: '>=18.0.0'} @@ -2407,10 +2646,6 @@ packages: resolution: {integrity: sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==} engines: {node: '>= 14'} - cron-parser@4.9.0: - resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} - engines: {node: '>=12.0.0'} - cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -2487,10 +2722,6 @@ packages: defu@6.1.7: resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} - denque@2.1.0: - resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} - engines: {node: '>=0.10'} - dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -2712,6 +2943,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.28.0: + resolution: {integrity: sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==} + engines: {node: '>=18'} + hasBin: true + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -2916,6 +3152,10 @@ packages: resolution: {integrity: sha512-P7oW7tLbYnhOLQk/Gv7cZgzgMPP/XN03K02/Jy6Y/NHzyIAIpxuZIM/YqAkfiXFPxA2CTm7NtCijK9EDu09u2w==} hasBin: true + fast-xml-parser@5.7.3: + resolution: {integrity: sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg==} + hasBin: true + fast-xml-parser@5.8.0: resolution: {integrity: sha512-6bIM7fsJxeo3uXv7OncQYsBAMPJ7V16Slahl/6M98C/i2q+vB1+4a0MtrvYwDFEUrwDSbAmeLDRXsOBwrL7yAg==} hasBin: true @@ -3150,10 +3390,6 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} - ioredis@5.10.1: - resolution: {integrity: sha512-HuEDBTI70aYdx1v6U97SbNx9F1+svQKBDo30o0b9fw055LMepzpOOd0Ccg9Q6tbqmBSJaMuY0fB7yw9/vjBYCA==} - engines: {node: '>=12.22.0'} - ipaddr.js@2.4.0: resolution: {integrity: sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==} engines: {node: '>= 10'} @@ -3394,12 +3630,6 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} - lodash.defaults@4.2.0: - resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} - - lodash.isarguments@3.1.0: - resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} - lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -3420,10 +3650,6 @@ packages: resolution: {integrity: sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A==} engines: {node: 20 || >=22} - luxon@3.7.2: - resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} - engines: {node: '>=12'} - make-cancellable-promise@1.3.2: resolution: {integrity: sha512-GCXh3bq/WuMbS+Ky4JBPW1hYTOU+znU+Q5m9Pu+pI8EoUqIHk9+tviOKC6/qhHh8C4/As3tzJ69IF32kdz85ww==} @@ -3621,13 +3847,6 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - msgpackr-extract@3.0.3: - resolution: {integrity: sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==} - hasBin: true - - msgpackr@2.0.1: - resolution: {integrity: sha512-9J+tqTEsbHqY8YohazYgty7LgerFIWxvMLpUjqETSmjHojtJm2WnX2kK/2a1fLI7CO7ERP1YSEUXMucz4j+yBA==} - mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} @@ -3679,9 +3898,6 @@ packages: resolution: {integrity: sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==} engines: {node: '>=10'} - node-abort-controller@3.1.1: - resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} - node-addon-api@7.1.1: resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} @@ -3689,10 +3905,6 @@ packages: resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==} engines: {node: '>= 0.4'} - node-gyp-build-optional-packages@5.2.2: - resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==} - hasBin: true - normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -3883,6 +4095,10 @@ packages: pino-std-serializers@7.1.0: resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==} + pino@10.3.1: + resolution: {integrity: sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==} + hasBin: true + pino@9.14.0: resolution: {integrity: sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==} hasBin: true @@ -4129,13 +4345,8 @@ packages: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} - redis-errors@1.2.0: - resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} - engines: {node: '>=4'} - - redis-parser@3.0.0: - resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} - engines: {node: '>=4'} + real-require@1.0.0: + resolution: {integrity: sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g==} redux@4.2.1: resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==} @@ -4330,9 +4541,6 @@ packages: stable-hash@0.0.5: resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} - standard-as-callback@2.1.0: - resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} - stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} @@ -4476,6 +4684,10 @@ packages: thread-stream@3.1.0: resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + thread-stream@4.2.0: + resolution: {integrity: sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ==} + engines: {node: '>=20'} + tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} @@ -4517,9 +4729,17 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + tsx@4.22.3: + resolution: {integrity: sha512-mdoNxBC/cSQObGGVQ5Bpn5i+yv7j68gk3Nfm3wFjcJg3Z0Mix9jzAFfP12prmm5eVGmDKtp0yyArrs0Q+8gZHg==} + engines: {node: '>=18.0.0'} + hasBin: true + tunnel-agent@0.6.0: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + tweetnacl@1.0.3: + resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -4776,6 +4996,38 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/client-s3@3.1050.0': + dependencies: + '@aws-crypto/sha1-browser': 5.2.0 + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.974.12 + '@aws-sdk/credential-provider-node': 3.972.43 + '@aws-sdk/middleware-bucket-endpoint': 3.972.14 + '@aws-sdk/middleware-expect-continue': 3.972.12 + '@aws-sdk/middleware-flexible-checksums': 3.974.20 + '@aws-sdk/middleware-location-constraint': 3.972.10 + '@aws-sdk/middleware-sdk-s3': 3.972.41 + '@aws-sdk/middleware-ssec': 3.972.10 + '@aws-sdk/signature-v4-multi-region': 3.996.27 + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/fetch-http-handler': 5.4.3 + '@smithy/node-http-handler': 4.7.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/core@3.974.12': + dependencies: + '@aws-sdk/types': 3.973.8 + '@aws-sdk/xml-builder': 3.972.24 + '@aws/lambda-invoke-store': 0.2.4 + '@smithy/core': 3.24.3 + '@smithy/signature-v4': 5.4.3 + '@smithy/types': 4.14.1 + bowser: 2.14.1 + tslib: 2.8.1 + '@aws-sdk/core@3.974.8': dependencies: '@aws-sdk/types': 3.973.8 @@ -4798,6 +5050,11 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 + '@aws-sdk/crc64-nvme@3.972.8': + dependencies: + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/credential-provider-env@3.972.34': dependencies: '@aws-sdk/core': 3.974.8 @@ -4806,6 +5063,14 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 + '@aws-sdk/credential-provider-env@3.972.38': + dependencies: + '@aws-sdk/core': 3.974.12 + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/credential-provider-http@3.972.36': dependencies: '@aws-sdk/core': 3.974.8 @@ -4819,6 +5084,16 @@ snapshots: '@smithy/util-stream': 4.6.1 tslib: 2.8.1 + '@aws-sdk/credential-provider-http@3.972.40': + dependencies: + '@aws-sdk/core': 3.974.12 + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/fetch-http-handler': 5.4.3 + '@smithy/node-http-handler': 4.7.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/credential-provider-ini@3.972.38': dependencies: '@aws-sdk/core': 3.974.8 @@ -4838,6 +5113,22 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-ini@3.972.42': + dependencies: + '@aws-sdk/core': 3.974.12 + '@aws-sdk/credential-provider-env': 3.972.38 + '@aws-sdk/credential-provider-http': 3.972.40 + '@aws-sdk/credential-provider-login': 3.972.42 + '@aws-sdk/credential-provider-process': 3.972.38 + '@aws-sdk/credential-provider-sso': 3.972.42 + '@aws-sdk/credential-provider-web-identity': 3.972.42 + '@aws-sdk/nested-clients': 3.997.10 + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/credential-provider-imds': 4.3.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/credential-provider-login@3.972.38': dependencies: '@aws-sdk/core': 3.974.8 @@ -4851,6 +5142,15 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-login@3.972.42': + dependencies: + '@aws-sdk/core': 3.974.12 + '@aws-sdk/nested-clients': 3.997.10 + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/credential-provider-node@3.972.39': dependencies: '@aws-sdk/credential-provider-env': 3.972.34 @@ -4868,6 +5168,20 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-node@3.972.43': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.38 + '@aws-sdk/credential-provider-http': 3.972.40 + '@aws-sdk/credential-provider-ini': 3.972.42 + '@aws-sdk/credential-provider-process': 3.972.38 + '@aws-sdk/credential-provider-sso': 3.972.42 + '@aws-sdk/credential-provider-web-identity': 3.972.42 + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/credential-provider-imds': 4.3.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/credential-provider-process@3.972.34': dependencies: '@aws-sdk/core': 3.974.8 @@ -4877,6 +5191,14 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 + '@aws-sdk/credential-provider-process@3.972.38': + dependencies: + '@aws-sdk/core': 3.974.12 + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/credential-provider-sso@3.972.38': dependencies: '@aws-sdk/core': 3.974.8 @@ -4890,6 +5212,16 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-sso@3.972.42': + dependencies: + '@aws-sdk/core': 3.974.12 + '@aws-sdk/nested-clients': 3.997.10 + '@aws-sdk/token-providers': 3.1049.0 + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/credential-provider-web-identity@3.972.38': dependencies: '@aws-sdk/core': 3.974.8 @@ -4902,6 +5234,15 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-web-identity@3.972.42': + dependencies: + '@aws-sdk/core': 3.974.12 + '@aws-sdk/nested-clients': 3.997.10 + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/middleware-bucket-endpoint@3.972.10': dependencies: '@aws-sdk/types': 3.973.8 @@ -4912,6 +5253,14 @@ snapshots: '@smithy/util-config-provider': 4.3.1 tslib: 2.8.1 + '@aws-sdk/middleware-bucket-endpoint@3.972.14': + dependencies: + '@aws-sdk/core': 3.974.12 + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/middleware-expect-continue@3.972.10': dependencies: '@aws-sdk/types': 3.973.8 @@ -4919,6 +5268,13 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 + '@aws-sdk/middleware-expect-continue@3.972.12': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/middleware-flexible-checksums@3.974.16': dependencies: '@aws-crypto/crc32': 5.2.0 @@ -4936,6 +5292,18 @@ snapshots: '@smithy/util-utf8': 4.3.1 tslib: 2.8.1 + '@aws-sdk/middleware-flexible-checksums@3.974.20': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@aws-crypto/crc32c': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/core': 3.974.12 + '@aws-sdk/crc64-nvme': 3.972.8 + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/middleware-host-header@3.972.10': dependencies: '@aws-sdk/types': 3.973.8 @@ -4980,6 +5348,16 @@ snapshots: '@smithy/util-utf8': 4.3.1 tslib: 2.8.1 + '@aws-sdk/middleware-sdk-s3@3.972.41': + dependencies: + '@aws-sdk/core': 3.974.12 + '@aws-sdk/signature-v4-multi-region': 3.996.27 + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/signature-v4': 5.4.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/middleware-ssec@3.972.10': dependencies: '@aws-sdk/types': 3.973.8 @@ -4997,6 +5375,19 @@ snapshots: '@smithy/util-retry': 4.4.1 tslib: 2.8.1 + '@aws-sdk/nested-clients@3.997.10': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.974.12 + '@aws-sdk/signature-v4-multi-region': 3.996.27 + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/fetch-http-handler': 5.4.3 + '@smithy/node-http-handler': 4.7.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/nested-clients@3.997.6': dependencies: '@aws-crypto/sha256-browser': 5.2.0 @@ -5069,6 +5460,14 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 + '@aws-sdk/signature-v4-multi-region@3.996.27': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/signature-v4': 5.4.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/token-providers@3.1041.0': dependencies: '@aws-sdk/core': 3.974.8 @@ -5081,6 +5480,15 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/token-providers@3.1049.0': + dependencies: + '@aws-sdk/core': 3.974.12 + '@aws-sdk/nested-clients': 3.997.10 + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.3 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + '@aws-sdk/types@3.973.8': dependencies: '@smithy/types': 4.14.1 @@ -5132,6 +5540,13 @@ snapshots: fast-xml-parser: 5.7.2 tslib: 2.8.1 + '@aws-sdk/xml-builder@3.972.24': + dependencies: + '@nodable/entities': 2.1.0 + '@smithy/types': 4.14.1 + fast-xml-parser: 5.7.3 + tslib: 2.8.1 + '@aws/lambda-invoke-store@0.2.4': {} '@babel/runtime@7.29.2': {} @@ -5230,6 +5645,9 @@ snapshots: '@esbuild/aix-ppc64@0.27.7': optional: true + '@esbuild/aix-ppc64@0.28.0': + optional: true + '@esbuild/android-arm64@0.18.20': optional: true @@ -5239,6 +5657,9 @@ snapshots: '@esbuild/android-arm64@0.27.7': optional: true + '@esbuild/android-arm64@0.28.0': + optional: true + '@esbuild/android-arm@0.18.20': optional: true @@ -5248,6 +5669,9 @@ snapshots: '@esbuild/android-arm@0.27.7': optional: true + '@esbuild/android-arm@0.28.0': + optional: true + '@esbuild/android-x64@0.18.20': optional: true @@ -5257,6 +5681,9 @@ snapshots: '@esbuild/android-x64@0.27.7': optional: true + '@esbuild/android-x64@0.28.0': + optional: true + '@esbuild/darwin-arm64@0.18.20': optional: true @@ -5266,6 +5693,9 @@ snapshots: '@esbuild/darwin-arm64@0.27.7': optional: true + '@esbuild/darwin-arm64@0.28.0': + optional: true + '@esbuild/darwin-x64@0.18.20': optional: true @@ -5275,6 +5705,9 @@ snapshots: '@esbuild/darwin-x64@0.27.7': optional: true + '@esbuild/darwin-x64@0.28.0': + optional: true + '@esbuild/freebsd-arm64@0.18.20': optional: true @@ -5284,6 +5717,9 @@ snapshots: '@esbuild/freebsd-arm64@0.27.7': optional: true + '@esbuild/freebsd-arm64@0.28.0': + optional: true + '@esbuild/freebsd-x64@0.18.20': optional: true @@ -5293,6 +5729,9 @@ snapshots: '@esbuild/freebsd-x64@0.27.7': optional: true + '@esbuild/freebsd-x64@0.28.0': + optional: true + '@esbuild/linux-arm64@0.18.20': optional: true @@ -5302,6 +5741,9 @@ snapshots: '@esbuild/linux-arm64@0.27.7': optional: true + '@esbuild/linux-arm64@0.28.0': + optional: true + '@esbuild/linux-arm@0.18.20': optional: true @@ -5311,6 +5753,9 @@ snapshots: '@esbuild/linux-arm@0.27.7': optional: true + '@esbuild/linux-arm@0.28.0': + optional: true + '@esbuild/linux-ia32@0.18.20': optional: true @@ -5320,6 +5765,9 @@ snapshots: '@esbuild/linux-ia32@0.27.7': optional: true + '@esbuild/linux-ia32@0.28.0': + optional: true + '@esbuild/linux-loong64@0.18.20': optional: true @@ -5329,6 +5777,9 @@ snapshots: '@esbuild/linux-loong64@0.27.7': optional: true + '@esbuild/linux-loong64@0.28.0': + optional: true + '@esbuild/linux-mips64el@0.18.20': optional: true @@ -5338,6 +5789,9 @@ snapshots: '@esbuild/linux-mips64el@0.27.7': optional: true + '@esbuild/linux-mips64el@0.28.0': + optional: true + '@esbuild/linux-ppc64@0.18.20': optional: true @@ -5347,6 +5801,9 @@ snapshots: '@esbuild/linux-ppc64@0.27.7': optional: true + '@esbuild/linux-ppc64@0.28.0': + optional: true + '@esbuild/linux-riscv64@0.18.20': optional: true @@ -5356,6 +5813,9 @@ snapshots: '@esbuild/linux-riscv64@0.27.7': optional: true + '@esbuild/linux-riscv64@0.28.0': + optional: true + '@esbuild/linux-s390x@0.18.20': optional: true @@ -5365,6 +5825,9 @@ snapshots: '@esbuild/linux-s390x@0.27.7': optional: true + '@esbuild/linux-s390x@0.28.0': + optional: true + '@esbuild/linux-x64@0.18.20': optional: true @@ -5374,12 +5837,18 @@ snapshots: '@esbuild/linux-x64@0.27.7': optional: true + '@esbuild/linux-x64@0.28.0': + optional: true + '@esbuild/netbsd-arm64@0.25.12': optional: true '@esbuild/netbsd-arm64@0.27.7': optional: true + '@esbuild/netbsd-arm64@0.28.0': + optional: true + '@esbuild/netbsd-x64@0.18.20': optional: true @@ -5389,12 +5858,18 @@ snapshots: '@esbuild/netbsd-x64@0.27.7': optional: true + '@esbuild/netbsd-x64@0.28.0': + optional: true + '@esbuild/openbsd-arm64@0.25.12': optional: true '@esbuild/openbsd-arm64@0.27.7': optional: true + '@esbuild/openbsd-arm64@0.28.0': + optional: true + '@esbuild/openbsd-x64@0.18.20': optional: true @@ -5404,12 +5879,18 @@ snapshots: '@esbuild/openbsd-x64@0.27.7': optional: true + '@esbuild/openbsd-x64@0.28.0': + optional: true + '@esbuild/openharmony-arm64@0.25.12': optional: true '@esbuild/openharmony-arm64@0.27.7': optional: true + '@esbuild/openharmony-arm64@0.28.0': + optional: true + '@esbuild/sunos-x64@0.18.20': optional: true @@ -5419,6 +5900,9 @@ snapshots: '@esbuild/sunos-x64@0.27.7': optional: true + '@esbuild/sunos-x64@0.28.0': + optional: true + '@esbuild/win32-arm64@0.18.20': optional: true @@ -5428,6 +5912,9 @@ snapshots: '@esbuild/win32-arm64@0.27.7': optional: true + '@esbuild/win32-arm64@0.28.0': + optional: true + '@esbuild/win32-ia32@0.18.20': optional: true @@ -5437,6 +5924,9 @@ snapshots: '@esbuild/win32-ia32@0.27.7': optional: true + '@esbuild/win32-ia32@0.28.0': + optional: true + '@esbuild/win32-x64@0.18.20': optional: true @@ -5446,6 +5936,9 @@ snapshots: '@esbuild/win32-x64@0.27.7': optional: true + '@esbuild/win32-x64@0.28.0': + optional: true + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@1.21.7))': dependencies: eslint: 9.39.4(jiti@1.21.7) @@ -5677,8 +6170,6 @@ snapshots: dependencies: '@swc/helpers': 0.5.21 - '@ioredis/commands@1.5.1': {} - '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -5702,24 +6193,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': - optional: true - - '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': - optional: true - - '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': - optional: true - - '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': - optional: true - - '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': - optional: true - - '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': - optional: true - '@napi-rs/canvas-android-arm64@0.1.100': optional: true @@ -5774,6 +6247,32 @@ snapshots: '@tybys/wasm-util': 0.10.2 optional: true + '@nats-io/jetstream@3.4.0': + dependencies: + '@nats-io/nats-core': 3.4.0 + + '@nats-io/kv@3.4.0': + dependencies: + '@nats-io/jetstream': 3.4.0 + '@nats-io/nats-core': 3.4.0 + + '@nats-io/nats-core@3.4.0': + dependencies: + '@nats-io/nkeys': 2.0.3 + '@nats-io/nuid': 3.0.0 + + '@nats-io/nkeys@2.0.3': + dependencies: + tweetnacl: 1.0.3 + + '@nats-io/nuid@3.0.0': {} + + '@nats-io/transport-node@3.4.0': + dependencies: + '@nats-io/nats-core': 3.4.0 + '@nats-io/nkeys': 2.0.3 + '@nats-io/nuid': 3.0.0 + '@next/env@15.5.18': {} '@next/eslint-plugin-next@15.5.18': @@ -5875,12 +6374,24 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 + '@smithy/core@3.24.3': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.14.2 + tslib: 2.8.1 + '@smithy/credential-provider-imds@4.3.1': dependencies: '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 + '@smithy/credential-provider-imds@4.3.3': + dependencies: + '@smithy/core': 3.24.3 + '@smithy/types': 4.14.2 + tslib: 2.8.1 + '@smithy/eventstream-serde-browser@4.3.1': dependencies: '@smithy/core': 3.24.1 @@ -5902,6 +6413,12 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 + '@smithy/fetch-http-handler@5.4.3': + dependencies: + '@smithy/core': 3.24.3 + '@smithy/types': 4.14.2 + tslib: 2.8.1 + '@smithy/hash-blob-browser@4.3.1': dependencies: '@smithy/core': 3.24.1 @@ -5972,6 +6489,12 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 + '@smithy/node-http-handler@4.7.3': + dependencies: + '@smithy/core': 3.24.3 + '@smithy/types': 4.14.2 + tslib: 2.8.1 + '@smithy/property-provider@4.3.1': dependencies: '@smithy/core': 3.24.1 @@ -5998,6 +6521,12 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 + '@smithy/signature-v4@5.4.3': + dependencies: + '@smithy/core': 3.24.3 + '@smithy/types': 4.14.2 + tslib: 2.8.1 + '@smithy/smithy-client@4.13.1': dependencies: '@smithy/core': 3.24.1 @@ -6008,6 +6537,10 @@ snapshots: dependencies: tslib: 2.8.1 + '@smithy/types@4.14.2': + dependencies: + tslib: 2.8.1 + '@smithy/url-parser@4.3.1': dependencies: '@smithy/core': 3.24.1 @@ -6093,10 +6626,10 @@ snapshots: dependencies: tslib: 2.8.1 - '@tailwindcss/typography@0.5.19(tailwindcss@3.4.19(tsx@4.21.0))': + '@tailwindcss/typography@0.5.19(tailwindcss@3.4.19(tsx@4.22.3))': dependencies: postcss-selector-parser: 6.0.10 - tailwindcss: 3.4.19(tsx@4.21.0) + tailwindcss: 3.4.19(tsx@4.22.3) '@tanstack/query-core@5.100.10': {} @@ -6652,17 +7185,6 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 - bullmq@5.76.10: - dependencies: - cron-parser: 4.9.0 - ioredis: 5.10.1 - msgpackr: 2.0.1 - node-abort-controller: 3.1.1 - semver: 7.8.0 - tslib: 2.8.1 - transitivePeerDependencies: - - supports-color - call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -6727,8 +7249,6 @@ snapshots: clsx@2.1.1: {} - cluster-key-slot@1.1.2: {} - cmpstr@3.3.0: {} color-convert@2.0.1: @@ -6779,10 +7299,6 @@ snapshots: crc-32: 1.2.2 readable-stream: 4.7.0 - cron-parser@4.9.0: - dependencies: - luxon: 3.7.2 - cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -6854,8 +7370,6 @@ snapshots: defu@6.1.7: {} - denque@2.1.0: {} - dequal@2.0.3: {} detect-libc@2.1.2: {} @@ -7138,6 +7652,35 @@ snapshots: '@esbuild/win32-ia32': 0.27.7 '@esbuild/win32-x64': 0.27.7 + esbuild@0.28.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.28.0 + '@esbuild/android-arm': 0.28.0 + '@esbuild/android-arm64': 0.28.0 + '@esbuild/android-x64': 0.28.0 + '@esbuild/darwin-arm64': 0.28.0 + '@esbuild/darwin-x64': 0.28.0 + '@esbuild/freebsd-arm64': 0.28.0 + '@esbuild/freebsd-x64': 0.28.0 + '@esbuild/linux-arm': 0.28.0 + '@esbuild/linux-arm64': 0.28.0 + '@esbuild/linux-ia32': 0.28.0 + '@esbuild/linux-loong64': 0.28.0 + '@esbuild/linux-mips64el': 0.28.0 + '@esbuild/linux-ppc64': 0.28.0 + '@esbuild/linux-riscv64': 0.28.0 + '@esbuild/linux-s390x': 0.28.0 + '@esbuild/linux-x64': 0.28.0 + '@esbuild/netbsd-arm64': 0.28.0 + '@esbuild/netbsd-x64': 0.28.0 + '@esbuild/openbsd-arm64': 0.28.0 + '@esbuild/openbsd-x64': 0.28.0 + '@esbuild/openharmony-arm64': 0.28.0 + '@esbuild/sunos-x64': 0.28.0 + '@esbuild/win32-arm64': 0.28.0 + '@esbuild/win32-ia32': 0.28.0 + '@esbuild/win32-x64': 0.28.0 + escape-string-regexp@4.0.0: {} escape-string-regexp@5.0.0: {} @@ -7429,6 +7972,13 @@ snapshots: path-expression-matcher: 1.5.0 strnum: 2.3.0 + fast-xml-parser@5.7.3: + dependencies: + '@nodable/entities': 2.1.0 + fast-xml-builder: 1.2.0 + path-expression-matcher: 1.5.0 + strnum: 2.3.0 + fast-xml-parser@5.8.0: dependencies: '@nodable/entities': 2.1.0 @@ -7701,20 +8251,6 @@ snapshots: hasown: 2.0.3 side-channel: 1.1.0 - ioredis@5.10.1: - dependencies: - '@ioredis/commands': 1.5.1 - cluster-key-slot: 1.1.2 - debug: 4.4.3 - denque: 2.1.0 - lodash.defaults: 4.2.0 - lodash.isarguments: 3.1.0 - redis-errors: 1.2.0 - redis-parser: 3.0.0 - standard-as-callback: 2.1.0 - transitivePeerDependencies: - - supports-color - ipaddr.js@2.4.0: {} is-alphabetical@2.0.1: {} @@ -7960,10 +8496,6 @@ snapshots: dependencies: p-locate: 5.0.0 - lodash.defaults@4.2.0: {} - - lodash.isarguments@3.1.0: {} - lodash.merge@4.6.2: {} lodash@4.18.1: {} @@ -7978,8 +8510,6 @@ snapshots: lru-cache@11.3.6: {} - luxon@3.7.2: {} - make-cancellable-promise@1.3.2: {} make-event-props@1.6.2: {} @@ -8375,22 +8905,6 @@ snapshots: ms@2.1.3: {} - msgpackr-extract@3.0.3: - dependencies: - node-gyp-build-optional-packages: 5.2.2 - optionalDependencies: - '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.3 - optional: true - - msgpackr@2.0.1: - optionalDependencies: - msgpackr-extract: 3.0.3 - mz@2.7.0: dependencies: any-promise: 1.3.0 @@ -8437,8 +8951,6 @@ snapshots: dependencies: semver: 7.8.0 - node-abort-controller@3.1.1: {} - node-addon-api@7.1.1: optional: true @@ -8449,11 +8961,6 @@ snapshots: object.entries: 1.1.9 semver: 6.3.1 - node-gyp-build-optional-packages@5.2.2: - dependencies: - detect-libc: 2.1.2 - optional: true - normalize-path@3.0.0: {} object-assign@4.1.1: {} @@ -8653,6 +9160,20 @@ snapshots: pino-std-serializers@7.1.0: {} + pino@10.3.1: + dependencies: + '@pinojs/redact': 0.4.0 + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 3.0.0 + pino-std-serializers: 7.1.0 + process-warning: 5.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.1 + thread-stream: 4.2.0 + pino@9.14.0: dependencies: '@pinojs/redact': 0.4.0 @@ -8691,13 +9212,13 @@ snapshots: camelcase-css: 2.0.1 postcss: 8.5.14 - postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.14)(tsx@4.21.0): + postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.14)(tsx@4.22.3): dependencies: lilconfig: 3.1.3 optionalDependencies: jiti: 1.21.7 postcss: 8.5.14 - tsx: 4.21.0 + tsx: 4.22.3 postcss-nested@6.2.0(postcss@8.5.14): dependencies: @@ -8936,11 +9457,7 @@ snapshots: real-require@0.2.0: {} - redis-errors@1.2.0: {} - - redis-parser@3.0.0: - dependencies: - redis-errors: 1.2.0 + real-require@1.0.0: {} redux@4.2.1: dependencies: @@ -9202,8 +9719,6 @@ snapshots: stable-hash@0.0.5: {} - standard-as-callback@2.1.0: {} - stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -9344,7 +9859,7 @@ snapshots: tabbable@6.4.0: {} - tailwindcss@3.4.19(tsx@4.21.0): + tailwindcss@3.4.19(tsx@4.22.3): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -9363,7 +9878,7 @@ snapshots: postcss: 8.5.14 postcss-import: 15.1.0(postcss@8.5.14) postcss-js: 4.1.0(postcss@8.5.14) - postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.14)(tsx@4.21.0) + postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.14)(tsx@4.22.3) postcss-nested: 6.2.0(postcss@8.5.14) postcss-selector-parser: 6.1.2 resolve: 1.22.12 @@ -9423,6 +9938,10 @@ snapshots: dependencies: real-require: 0.2.0 + thread-stream@4.2.0: + dependencies: + real-require: 1.0.0 + tiny-invariant@1.3.3: {} tinyglobby@0.2.16: @@ -9462,10 +9981,18 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + tsx@4.22.3: + dependencies: + esbuild: 0.28.0 + optionalDependencies: + fsevents: 2.3.3 + tunnel-agent@0.6.0: dependencies: safe-buffer: 5.2.1 + tweetnacl@1.0.3: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1