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