From 2cde9056187eda6295c16eb7138652ffbd475938 Mon Sep 17 00:00:00 2001 From: Paolo Insogna Date: Fri, 12 Jun 2026 12:18:41 +0000 Subject: [PATCH 1/3] feat: Added separate Database application. Signed-off-by: Paolo Insogna --- acceptance/scripts/run-managed-local.ts | 1 + acceptance/scripts/run-managed-watt-local.ts | 520 ++ acceptance/specs/database-watt.test.ts | 444 ++ docs/database-watt-postgresql-scope.md | 18 + package-lock.json | 6670 +++++++++++------ package.json | 10 +- src/admin-app.test.ts | 76 +- src/admin-app.ts | 4 +- src/database/cancellation.ts | 132 + src/database/config.ts | 111 + src/database/destinations.ts | 117 + src/database/errors.ts | 117 + src/database/index.ts | 346 + src/database/locks.ts | 216 + src/database/metrics.ts | 36 + src/database/pg-lib-connection.d.ts | 11 + src/database/pools.ts | 225 + src/database/result-limits.ts | 17 + src/database/ssl.ts | 32 + src/database/tests/cancellation.test.ts | 74 + src/database/tests/errors.test.ts | 45 + src/database/tests/index.test.ts | 304 + src/database/tests/locks.test.ts | 121 + src/database/tests/result-limits.test.ts | 29 + src/database/tests/validation.test.ts | 76 + src/database/types.ts | 60 + src/database/validation.ts | 85 + src/internal/database/client.test.ts | 141 + src/internal/database/client.ts | 51 +- src/internal/database/migrations/migrate.ts | 1 + src/internal/database/multitenant-pg.test.ts | 83 +- src/internal/database/multitenant-pg.ts | 9 +- src/internal/database/pg-connection.ts | 21 +- src/internal/database/watt-connection.test.ts | 218 + src/internal/database/watt-connection.ts | 382 + watt.database.json | 7 + watt.json | 43 +- watt.storage.json | 7 + 38 files changed, 8646 insertions(+), 2214 deletions(-) create mode 100644 acceptance/scripts/run-managed-watt-local.ts create mode 100644 acceptance/specs/database-watt.test.ts create mode 100644 docs/database-watt-postgresql-scope.md create mode 100644 src/database/cancellation.ts create mode 100644 src/database/config.ts create mode 100644 src/database/destinations.ts create mode 100644 src/database/errors.ts create mode 100644 src/database/index.ts create mode 100644 src/database/locks.ts create mode 100644 src/database/metrics.ts create mode 100644 src/database/pg-lib-connection.d.ts create mode 100644 src/database/pools.ts create mode 100644 src/database/result-limits.ts create mode 100644 src/database/ssl.ts create mode 100644 src/database/tests/cancellation.test.ts create mode 100644 src/database/tests/errors.test.ts create mode 100644 src/database/tests/index.test.ts create mode 100644 src/database/tests/locks.test.ts create mode 100644 src/database/tests/result-limits.test.ts create mode 100644 src/database/tests/validation.test.ts create mode 100644 src/database/types.ts create mode 100644 src/database/validation.ts create mode 100644 src/internal/database/client.test.ts create mode 100644 src/internal/database/watt-connection.test.ts create mode 100644 src/internal/database/watt-connection.ts create mode 100644 watt.database.json create mode 100644 watt.storage.json diff --git a/acceptance/scripts/run-managed-local.ts b/acceptance/scripts/run-managed-local.ts index b01ddff41..a7c4fc233 100644 --- a/acceptance/scripts/run-managed-local.ts +++ b/acceptance/scripts/run-managed-local.ts @@ -19,6 +19,7 @@ const serverIsMultitenant = isMultitenantServer(serverEnv) const acceptanceRunEnv: NodeJS.ProcessEnv = { ...process.env, ACCEPTANCE_BASE_URL: baseUrl, + ACCEPTANCE_DATABASE_WATT: 'false', ACCEPTANCE_PROFILE: profile, ACCEPTANCE_S3_ENDPOINT: acceptanceEnv('ACCEPTANCE_S3_ENDPOINT') ?? `${baseUrl}/s3`, STORAGE_BACKEND: acceptanceEnv('STORAGE_BACKEND') ?? serverEnv.STORAGE_BACKEND, diff --git a/acceptance/scripts/run-managed-watt-local.ts b/acceptance/scripts/run-managed-watt-local.ts new file mode 100644 index 000000000..743aeeffc --- /dev/null +++ b/acceptance/scripts/run-managed-watt-local.ts @@ -0,0 +1,520 @@ +import { type ChildProcess, spawn } from 'node:child_process' +import fs from 'node:fs' +import { createServer, type Server as HttpServer } from 'node:http' +import path from 'node:path' +import { RuntimeApiClient } from '@platformatic/control' +import dotenv from 'dotenv' + +const inheritedEnv = { ...process.env } +loadAcceptanceEnvFile() + +const args = process.argv.slice(2) +const profile = readArg('profile') ?? acceptanceEnv('ACCEPTANCE_PROFILE') ?? 'core' +const serverEnv = loadServerEnvFiles(inheritedEnv) +configureManagedLocalQueueEnv(serverEnv) +serverEnv.LOG_LEVEL = serverEnv.LOG_LEVEL || 'info' +serverEnv.NODE_ENV = 'test' +serverEnv.UPLOAD_FILE_SIZE_LIMIT = serverEnv.UPLOAD_FILE_SIZE_LIMIT || '524288000' +serverEnv.WORKERS_NUM = serverEnv.WORKERS_NUM || '2' +serverEnv.PLT_MANAGEMENT_API = serverEnv.PLT_MANAGEMENT_API || 'true' +serverEnv.WATT_HEALTH_ENABLED = serverEnv.WATT_HEALTH_ENABLED || 'false' + +const serverPort = serverEnv.SERVER_PORT || serverEnv.PORT || '5000' +const baseUrl = acceptanceEnv('ACCEPTANCE_BASE_URL') ?? `http://127.0.0.1:${serverPort}` +const serverIsMultitenant = isMultitenantServer(serverEnv) +const acceptanceRunEnv: NodeJS.ProcessEnv = { + ...process.env, + ACCEPTANCE_BASE_URL: baseUrl, + ACCEPTANCE_DATABASE_WATT: 'true', + ACCEPTANCE_PROFILE: profile, + ACCEPTANCE_SERVICE_KEY: acceptanceEnv('ACCEPTANCE_SERVICE_KEY') ?? serverEnv.SERVICE_KEY, + ACCEPTANCE_S3_ACCESS_KEY_ID: + acceptanceEnv('ACCEPTANCE_S3_ACCESS_KEY_ID') ?? serverEnv.S3_PROTOCOL_ACCESS_KEY_ID, + ACCEPTANCE_S3_ENDPOINT: acceptanceEnv('ACCEPTANCE_S3_ENDPOINT') ?? `${baseUrl}/s3`, + ACCEPTANCE_S3_SECRET_ACCESS_KEY: + acceptanceEnv('ACCEPTANCE_S3_SECRET_ACCESS_KEY') ?? serverEnv.S3_PROTOCOL_ACCESS_KEY_SECRET, + ACCEPTANCE_TUS_ENDPOINT: `${baseUrl}/upload/resumable`, + STORAGE_BACKEND: acceptanceEnv('STORAGE_BACKEND') ?? serverEnv.STORAGE_BACKEND, +} + +let server: ChildProcess | undefined +let cdnPurgeServer: HttpServer | undefined +let provisionedS3Credential: ProvisionedS3Credential | undefined + +main().catch((error) => { + console.error(error) + process.exit(1) +}) + +async function waitForWattApplication(applicationId: string, timeoutMs: number) { + const client = new RuntimeApiClient() + const started = Date.now() + let lastError: unknown + + try { + while (Date.now() - started < timeoutMs) { + try { + const runtime = await client.getMatchingRuntime() + const application = await client.getRuntimeApplications(runtime.pid).then(({ applications }) => { + return applications.find((application) => application.id === applicationId) + }) + + if (application?.status === 'started') { + return + } + + lastError = new Error(`Application ${applicationId} status is ${application?.status ?? 'unknown'}`) + } catch (error) { + lastError = error + } + + await new Promise((resolve) => setTimeout(resolve, 500)) + } + } finally { + await client.close() + } + + throw new Error(`Timed out waiting for Watt application ${applicationId}: ${String(lastError)}`) +} + +async function main() { + try { + if (process.env.ACCEPTANCE_SKIP_INFRA !== 'true') { + await run('npm', ['run', resolveInfraRestartScript()], serverEnv) + await run('npm', ['run', 'test:dummy-data'], serverEnv) + } + + if (isTruthy(acceptanceRunEnv.ACCEPTANCE_ENABLE_CDN) && !serverEnv.CDN_PURGE_ENDPOINT_URL) { + const purge = await startLocalCdnPurgeServer() + cdnPurgeServer = purge.server + serverEnv.CDN_PURGE_ENDPOINT_URL = purge.url + } + + await run('npm', ['run', 'build'], serverEnv) + + server = spawn(localBin('wattpm'), ['start'], { + detached: process.platform !== 'win32', + env: serverEnv, + stdio: ['ignore', 'pipe', 'pipe'], + }) + prefixOutput(server.stdout, '[watt] ') + prefixOutput(server.stderr, '[watt] ') + + await waitForStatus(`${baseUrl}/status`, 60_000) + await waitForWattApplication('storage', 60_000) + await waitForWattApplication('database', 60_000) + + if (serverIsMultitenant) { + provisionedS3Credential = await provisionLocalMultitenantTenant(serverEnv) + acceptanceRunEnv.ACCEPTANCE_ADMIN_URL = provisionedS3Credential.adminUrl + acceptanceRunEnv.ACCEPTANCE_ADMIN_API_KEY = provisionedS3Credential.adminApiKey + acceptanceRunEnv.ACCEPTANCE_TENANT_ID = provisionedS3Credential.tenantId + acceptanceRunEnv.ACCEPTANCE_S3_ACCESS_KEY_ID = provisionedS3Credential.accessKey + acceptanceRunEnv.ACCEPTANCE_S3_SECRET_ACCESS_KEY = provisionedS3Credential.secretKey + } else if (isTruthy(acceptanceRunEnv.ACCEPTANCE_ENABLE_ADMIN)) { + acceptanceRunEnv.ACCEPTANCE_ENABLE_ADMIN = 'false' + acceptanceRunEnv.ACCEPTANCE_ADMIN_URL = '' + acceptanceRunEnv.ACCEPTANCE_ADMIN_API_KEY = '' + process.stderr.write( + '[acceptance] disabled admin acceptance for managed single-tenant Watt server\n' + ) + } + + await run('npm', ['run', 'acceptance:run', '--', ...args], acceptanceRunEnv) + } finally { + if (provisionedS3Credential) { + await deleteProvisionedS3Credential(provisionedS3Credential).catch((error) => { + process.stderr.write( + `[acceptance] failed to delete local S3 credential: ${String(error)}\n` + ) + }) + } + + if (server) { + await stopServer(server) + } + + if (cdnPurgeServer) { + await closeHttpServer(cdnPurgeServer).catch((error) => { + process.stderr.write(`[acceptance] failed to stop CDN purge stub: ${String(error)}\n`) + }) + } + } +} + +interface ProvisionedS3Credential { + accessKey: string + adminApiKey: string + adminUrl: string + id: string + secretKey: string + tenantId: string +} + +interface S3CredentialResponse { + access_key?: string + id?: string + secret_key?: string +} + +async function provisionLocalMultitenantTenant( + env: NodeJS.ProcessEnv +): Promise { + const adminPort = env.SERVER_ADMIN_PORT || '5001' + const adminUrl = `http://127.0.0.1:${adminPort}` + const adminApiKey = firstCsvValue(requiredEnv(env, 'SERVER_ADMIN_API_KEYS', 'ADMIN_API_KEYS')) + const tenantId = requiredEnv(env, 'TENANT_ID') + + await waitForStatus(`${adminUrl}/status`, 60_000) + + await requestAdmin(adminUrl, adminApiKey, 'PUT', `/tenants/${encodeURIComponent(tenantId)}`, { + anonKey: requiredEnv(env, 'ANON_KEY'), + databasePoolUrl: env.DATABASE_POOL_URL || undefined, + databaseUrl: requiredEnv(env, 'DATABASE_URL'), + features: { + icebergCatalog: { + enabled: isTruthy(env.ICEBERG_ENABLED), + maxCatalogs: envNumber(env.ICEBERG_MAX_CATALOGS, 2), + maxNamespaces: envNumber(env.ICEBERG_MAX_NAMESPACES, 25), + maxTables: envNumber(env.ICEBERG_MAX_TABLES, 10), + }, + imageTransformation: { + enabled: isTruthy(env.IMAGE_TRANSFORMATION_ENABLED), + maxResolution: envNumber(env.IMAGE_TRANSFORMATION_LIMIT_MAX_SIZE, 2000), + }, + purgeCache: { + enabled: isTruthy(acceptanceRunEnv.ACCEPTANCE_ENABLE_CDN), + }, + s3Protocol: { + enabled: true, + }, + vectorBuckets: { + enabled: isTruthy(env.VECTOR_ENABLED), + maxBuckets: envNumber(env.VECTOR_MAX_BUCKETS, 10), + maxIndexes: envNumber(env.VECTOR_MAX_INDEXES, 20), + }, + }, + fileSizeLimit: envNumber(env.UPLOAD_FILE_SIZE_LIMIT, 524288000), + jwtSecret: requiredEnv(env, 'AUTH_JWT_SECRET', 'PGRST_JWT_SECRET'), + serviceKey: requiredEnv(env, 'SERVICE_KEY'), + }) + + const credential = await requestAdmin( + adminUrl, + adminApiKey, + 'POST', + `/s3/${encodeURIComponent(tenantId)}/credentials`, + { + claims: { + role: env.DB_SERVICE_ROLE || 'service_role', + sub: 'local-acceptance', + }, + description: `local-acceptance-${Date.now()}`, + }, + 201 + ) + + if (!credential?.id || !credential.access_key || !credential.secret_key) { + throw new Error('Local multitenant S3 credential response was incomplete') + } + + return { + accessKey: credential.access_key, + adminApiKey, + adminUrl, + id: credential.id, + secretKey: credential.secret_key, + tenantId, + } +} + +async function deleteProvisionedS3Credential(credential: ProvisionedS3Credential) { + await requestAdmin( + credential.adminUrl, + credential.adminApiKey, + 'DELETE', + `/s3/${encodeURIComponent(credential.tenantId)}/credentials`, + { + id: credential.id, + }, + [200, 204] + ) +} + +async function requestAdmin( + adminUrl: string, + adminApiKey: string, + method: string, + route: string, + body?: Record, + expectedStatus: number | number[] = 204 +): Promise { + const response = await fetch(new URL(route.replace(/^\/+/, ''), `${adminUrl}/`), { + body: body ? JSON.stringify(body) : undefined, + headers: { + apikey: adminApiKey, + ...(body ? { 'content-type': 'application/json' } : undefined), + }, + method, + }) + const text = await response.text() + + if (!statusMatches(response.status, expectedStatus)) { + throw new Error( + [ + `Unexpected admin status for ${method} ${route}`, + `expected: ${Array.isArray(expectedStatus) ? expectedStatus.join(', ') : expectedStatus}`, + `received: ${response.status}`, + `body: ${text}`, + ].join('\n') + ) + } + + return parseJson(text) +} + +function startLocalCdnPurgeServer(): Promise<{ server: HttpServer; url: string }> { + return new Promise((resolve, reject) => { + const server = createServer((request, response) => { + request.resume() + + if ( + request.method === 'POST' && + new URL(request.url ?? '/', 'http://127.0.0.1').pathname === '/purge' + ) { + response.writeHead(200, { 'content-type': 'application/json' }) + response.end(JSON.stringify({ message: 'success' })) + return + } + + response.writeHead(404, { 'content-type': 'application/json' }) + response.end(JSON.stringify({ message: 'not found' })) + }) + + server.once('error', reject) + server.listen(0, '127.0.0.1', () => { + server.off('error', reject) + const address = server.address() + if (!address || typeof address === 'string') { + reject(new Error('Local CDN purge stub did not bind to a TCP port')) + return + } + + resolve({ + server, + url: `http://127.0.0.1:${address.port}`, + }) + }) + }) +} + +function closeHttpServer(server: HttpServer): Promise { + return new Promise((resolve, reject) => { + server.close((error) => { + if (error) { + reject(error) + return + } + + resolve() + }) + }) +} + +function requiredEnv(env: NodeJS.ProcessEnv, name: string, fallbackName?: string): string { + const value = env[name] || (fallbackName ? env[fallbackName] : undefined) + + if (!value) { + throw new Error( + `Missing required local acceptance environment variable: ${ + fallbackName ? `${name} or ${fallbackName}` : name + }` + ) + } + + return value +} + +function envNumber(value: string | undefined, fallback: number): number { + if (!value) { + return fallback + } + + const number = Number(value) + return Number.isFinite(number) ? number : fallback +} + +function firstCsvValue(value: string): string { + return value.split(',')[0]?.trim() || value +} + +function isTruthy(value: string | undefined): boolean { + return value === '1' || value === 'true' || value === 'yes' +} + +function isMultitenantServer(env: NodeJS.ProcessEnv): boolean { + return isTruthy(env.MULTI_TENANT) || isTruthy(env.IS_MULTITENANT) +} + +function configureManagedLocalQueueEnv(env: NodeJS.ProcessEnv) { + if ( + isTruthy(env.PG_QUEUE_ENABLE) && + isMultitenantServer(env) && + !env.PG_QUEUE_CONNECTION_URL && + env.DATABASE_MULTITENANT_URL + ) { + env.PG_QUEUE_CONNECTION_URL = env.DATABASE_MULTITENANT_URL + } +} + +function statusMatches(status: number, expected: number | number[]) { + return Array.isArray(expected) ? expected.includes(status) : status === expected +} + +function parseJson(text: string): T | undefined { + if (!text) { + return undefined + } + + return JSON.parse(text) as T +} + +function resolveInfraRestartScript() { + const script = acceptanceEnv('ACCEPTANCE_INFRA_RESTART_SCRIPT') ?? 'infra:restart:ci' + const allowed = new Set(['infra:restart:ci', 'infra:restart:ci:oriole']) + + if (!allowed.has(script)) { + throw new Error(`Unsupported ACCEPTANCE_INFRA_RESTART_SCRIPT: ${script}`) + } + + return script +} + +function run(cmd: string, runArgs: string[], runEnv: NodeJS.ProcessEnv): Promise { + return new Promise((resolve, reject) => { + const child = spawn(command(cmd), runArgs, { + env: runEnv, + stdio: 'inherit', + }) + + child.on('exit', (code, signal) => { + if (code === 0) { + resolve() + } else if (signal) { + reject(new Error(`${cmd} ${runArgs.join(' ')} terminated with ${signal}`)) + } else { + reject(new Error(`${cmd} ${runArgs.join(' ')} exited with ${code}`)) + } + }) + child.on('error', reject) + }) +} + +async function waitForStatus(url: string, timeoutMs: number) { + const started = Date.now() + let lastError: unknown + + while (Date.now() - started < timeoutMs) { + let response: Response | undefined + + try { + response = await fetch(url) + if (response.status === 200) { + return + } + } catch (error) { + lastError = error + } finally { + await response?.body?.cancel() + } + + await new Promise((resolve) => setTimeout(resolve, 500)) + } + + throw new Error(`Timed out waiting for ${url}: ${String(lastError)}`) +} + +async function stopServer(child: ChildProcess) { + if (child.exitCode !== null || child.signalCode !== null) { + return + } + + if (process.platform === 'win32' || !child.pid) { + child.kill() + return + } + + try { + process.kill(-child.pid, 'SIGTERM') + } catch (error) { + if (!(typeof error === 'object' && error !== null && 'code' in error && error.code === 'ESRCH')) { + throw error + } + } +} + +function readArg(name: string) { + const flag = `--${name}` + const equalsPrefix = `${flag}=` + + for (let index = 0; index < args.length; index++) { + if (args[index] === flag) { + return args[index + 1] + } + if (args[index].startsWith(equalsPrefix)) { + return args[index].slice(equalsPrefix.length) + } + } + + return undefined +} + +function prefixOutput(stream: NodeJS.ReadableStream | null, prefix: string) { + stream?.setEncoding('utf8') + stream?.on('data', (chunk: string) => { + for (const line of chunk.split(/\r?\n/)) { + if (line) { + process.stderr.write(`${prefix}${line}\n`) + } + } + }) +} + +function command(cmd: string) { + return process.platform === 'win32' ? `${cmd}.cmd` : cmd +} + +function localBin(cmd: string) { + return path.resolve('node_modules', '.bin', command(cmd)) +} + +function acceptanceEnv(name: string): string | undefined { + const value = process.env[name] + return value === undefined || value === '' ? undefined : value +} + +function loadAcceptanceEnvFile() { + const acceptanceEnvPath = process.env.ACCEPTANCE_ENV_FILE ?? '.env.acceptance' + dotenv.config({ path: path.resolve(acceptanceEnvPath), override: false }) +} + +function loadServerEnvFiles(baseEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv { + const env = { ...baseEnv } + loadEnvFileInto(env, '.env.test') + loadEnvFileInto(env, '.env') + return env +} + +function loadEnvFileInto(env: NodeJS.ProcessEnv, envPath: string) { + const resolvedPath = path.resolve(envPath) + if (!fs.existsSync(resolvedPath)) { + return + } + + const parsed = dotenv.parse(fs.readFileSync(resolvedPath)) + for (const [name, value] of Object.entries(parsed)) { + if (env[name] === undefined) { + env[name] = value + } + } +} diff --git a/acceptance/specs/database-watt.test.ts b/acceptance/specs/database-watt.test.ts new file mode 100644 index 000000000..1fb43f972 --- /dev/null +++ b/acceptance/specs/database-watt.test.ts @@ -0,0 +1,444 @@ +import { randomUUID } from 'node:crypto' +import { describeAcceptance, encodePathSegments, getAcceptanceConfig } from '../support/config' +import { createRestClient } from '../support/http' +import { + cleanupRestResources, + createRestBucket, + requireServiceKey, + uniqueBucketName, + uniqueObjectKey, + uploadRestObject, +} from '../support/resources' + +type DatabaseWattStats = { + acquire: number + beginTransaction: number + cancel: number + commitTransaction: number + lockedQuery: number + query: number + release: number + rollbackTransaction: number +} + +type BucketResponse = { + id: string + name: string + public: boolean +} + +type RollbackResponse = { + bucketName: string +} + +type SavepointResponse = { + innerBucket: string + outerBucket: string +} + +type QueryRowsResponse = { + rows: Array<{ value: number }> +} + +type LockResponse = { + lockId: string +} + +type ErrorResponse = { + code: string + destination?: string + message: string +} + +const describeDatabaseWattAcceptance = process.env.ACCEPTANCE_DATABASE_WATT === 'true' ? describeAcceptance : describe.skip + +function testDestination(): string { + return process.env.ACCEPTANCE_TENANT_ID || process.env.TENANT_ID || 'default' +} + +function sendDatabaseMessage(message: string, payload: unknown): Promise { + return sendWattMessage('database', message, payload) +} + +function isDatabaseError(result: unknown): result is ErrorResponse { + return typeof result === 'object' && result !== null && 'code' in result && 'message' in result +} + +async function checkedResult(resultPromise: Promise): Promise { + const result = await resultPromise + if (isDatabaseError(result)) { + throw new Error(result.message) + } + return result as T +} + +async function beginTransaction(destination = testDestination()): Promise { + return checkedResult( + sendDatabaseMessage('database.beginTransaction', { + destination, + requestId: randomUUID(), + }) + ) +} + +async function queryDatabaseWatt(destination = testDestination()): Promise { + return sendDatabaseMessage('database.query', { + destination, + requestId: randomUUID(), + sql: 'SELECT 1 as value', + }) +} + +async function masterTransaction(): Promise<{ value: number | undefined }> { + const tx = await beginTransaction('master') + + try { + const result = await checkedResult( + sendDatabaseMessage('database.lockedQuery', { + lockId: tx.lockId, + requestId: randomUUID(), + sql: 'SELECT 1 as value', + }) + ) + await checkedResult(sendDatabaseMessage('database.commitTransaction', { lockId: tx.lockId })) + return { value: result.rows[0]?.value } + } catch (error) { + await sendDatabaseMessage('database.rollbackTransaction', { lockId: tx.lockId }).catch(() => undefined) + throw error + } +} + +async function rollbackDatabaseWatt(): Promise { + const bucketName = `db-watt-rollback-${Date.now()}` + const tx = await beginTransaction() + + try { + await checkedResult( + sendDatabaseMessage('database.lockedQuery', { + lockId: tx.lockId, + requestId: randomUUID(), + sql: `INSERT INTO storage.buckets (id, name, owner, public) VALUES ($1, $1, $2, false)`, + values: [bucketName, randomUUID()], + }) + ) + await checkedResult(sendDatabaseMessage('database.rollbackTransaction', { lockId: tx.lockId })) + return { bucketName } + } catch (error) { + await sendDatabaseMessage('database.rollbackTransaction', { lockId: tx.lockId }).catch(() => undefined) + throw error + } +} + +async function savepointDatabaseWatt(): Promise { + const innerBucket = `db-watt-savepoint-inner-${Date.now()}` + const outerBucket = `db-watt-savepoint-outer-${Date.now()}` + const tx = await beginTransaction() + + try { + await checkedResult( + sendDatabaseMessage('database.lockedQuery', { + lockId: tx.lockId, + requestId: randomUUID(), + sql: `INSERT INTO storage.buckets (id, name, owner, public) VALUES ($1, $1, $2, false)`, + values: [outerBucket, randomUUID()], + }) + ) + await checkedResult( + sendDatabaseMessage('database.lockedQuery', { + lockId: tx.lockId, + requestId: randomUUID(), + sql: 'SAVEPOINT database_watt_acceptance', + }) + ) + await checkedResult( + sendDatabaseMessage('database.lockedQuery', { + lockId: tx.lockId, + requestId: randomUUID(), + sql: `INSERT INTO storage.buckets (id, name, owner, public) VALUES ($1, $1, $2, false)`, + values: [innerBucket, randomUUID()], + }) + ) + await checkedResult( + sendDatabaseMessage('database.lockedQuery', { + lockId: tx.lockId, + requestId: randomUUID(), + sql: 'ROLLBACK TO SAVEPOINT database_watt_acceptance', + }) + ) + await checkedResult(sendDatabaseMessage('database.commitTransaction', { lockId: tx.lockId })) + return { innerBucket, outerBucket } + } catch (error) { + await sendDatabaseMessage('database.rollbackTransaction', { lockId: tx.lockId }).catch(() => undefined) + throw error + } +} + +async function sleepDatabaseWatt(): Promise { + const requestId = randomUUID() + const query = sendDatabaseMessage('database.query', { + destination: testDestination(), + requestId, + sql: 'SELECT pg_sleep(10)', + }) + + setTimeout(() => { + sendDatabaseMessage('database.cancel', { requestId }).catch(() => undefined) + }, 50).unref() + + return query +} + +async function missingDestinationDatabaseWatt(): Promise { + return sendDatabaseMessage('database.query', { + destination: `missing-${randomUUID()}`, + requestId: randomUUID(), + sql: 'SELECT 1', + }) +} + +async function concurrentQueriesDatabaseWatt(): Promise<{ count: number }> { + const results = await Promise.all( + Array.from({ length: 5 }, () => + sendDatabaseMessage('database.query', { + destination: testDestination(), + requestId: randomUUID(), + sql: 'SELECT 1 as value', + }) + ) + ) + const error = results.find(isDatabaseError) + + if (error) { + throw new Error(error.message) + } + + return { count: results.length } +} + +async function getDatabaseWattStats(): Promise { + return sendDatabaseMessage('database.test.stats', {}) +} + +async function resetDatabaseWattStats(): Promise { + await sendDatabaseMessage('database.test.resetStats', {}) +} + +describeDatabaseWattAcceptance( + 'Database Watt E2E', + { + destructive: true, + profiles: ['core'], + }, + () => { + it('executes stateless queries in the Database Watt worker', async () => { + await resetDatabaseWattStats() + + const response = await queryDatabaseWatt() + const stats = await getDatabaseWattStats() + + expect(response.rows[0]).toEqual({ value: 1 }) + expect(stats.query).toBeGreaterThanOrEqual(1) + }) + + it('executes master database queries through Database Watt', async () => { + const config = getAcceptanceConfig() + + if (!config.tenantId) { + expect(config.tenantId).toBeUndefined() + return + } + + await resetDatabaseWattStats() + const response = await queryDatabaseWatt('master') + const stats = await getDatabaseWattStats() + + expect(response.rows[0]).toEqual({ value: 1 }) + expect(stats.query).toBeGreaterThanOrEqual(1) + }) + + it('executes master database transactions through Database Watt', async () => { + const config = getAcceptanceConfig() + + if (!config.tenantId) { + expect(config.tenantId).toBeUndefined() + return + } + + await resetDatabaseWattStats() + const response = await masterTransaction() + const stats = await getDatabaseWattStats() + + expect(response).toEqual({ value: 1 }) + expect(stats.beginTransaction).toBeGreaterThanOrEqual(1) + expect(stats.lockedQuery).toBeGreaterThanOrEqual(1) + expect(stats.commitTransaction).toBeGreaterThanOrEqual(1) + }) + + it('commits REST object changes through Database Watt transactions', async () => { + const client = createRestClient() + const token = requireServiceKey() + const bucketName = uniqueBucketName('dbwatt-commit') + const objectKey = uniqueObjectKey('dbwatt-commit') + await resetDatabaseWattStats() + + try { + await createRestBucket(bucketName, { isPublic: false }) + await uploadRestObject(bucketName, objectKey, 'database-watt-commit') + + const read = await client.request('GET', `/object/${bucketName}/${encodePathSegments(objectKey)}`, { + expectedStatus: 200, + token, + }) + const stats = await getDatabaseWattStats() + + expect(read.body).toBe('database-watt-commit') + expect(stats.beginTransaction).toBeGreaterThanOrEqual(1) + expect(stats.lockedQuery).toBeGreaterThanOrEqual(1) + expect(stats.commitTransaction).toBeGreaterThanOrEqual(1) + } finally { + await cleanupRestResources(bucketName, [objectKey], client) + } + }) + + it('rolls back failed transaction work and leaves no partial bucket state', async () => { + const client = createRestClient() + const token = requireServiceKey() + await resetDatabaseWattStats() + + const rollback = await rollbackDatabaseWatt() + const bucketName = rollback.bucketName + expect(bucketName).toBeTruthy() + + const lookup = await client.request('GET', `/bucket/${bucketName}`, { + expectedStatus: 400, + token, + }) + const stats = await getDatabaseWattStats() + + expect(lookup.status).toBe(400) + expect(stats.rollbackTransaction).toBeGreaterThanOrEqual(1) + }) + + it('preserves nested savepoint semantics in Database Watt transactions', async () => { + const client = createRestClient() + const token = requireServiceKey() + await resetDatabaseWattStats() + + const savepoint = await savepointDatabaseWatt() + const outerBucket = savepoint.outerBucket + const innerBucket = savepoint.innerBucket + + try { + expect(outerBucket).toBeTruthy() + expect(innerBucket).toBeTruthy() + + const outer = await client.request('GET', `/bucket/${outerBucket}`, { + expectedStatus: 200, + token, + }) + const inner = await client.request('GET', `/bucket/${innerBucket}`, { + expectedStatus: 400, + token, + }) + const stats = await getDatabaseWattStats() + + expect(outer.json?.id).toBe(outerBucket) + expect(inner.status).toBe(400) + expect(stats.lockedQuery).toBeGreaterThanOrEqual(3) + expect(stats.commitTransaction).toBeGreaterThanOrEqual(1) + } finally { + if (outerBucket) { + await cleanupRestResources(outerBucket, [], client) + } + } + }) + + it('preserves storage error mapping when Database Watt returns PostgreSQL errors', async () => { + const client = createRestClient() + const token = requireServiceKey() + const bucketName = uniqueBucketName('dbwatt-error') + await resetDatabaseWattStats() + + try { + await createRestBucket(bucketName, { isPublic: false }) + const duplicate = await client.request('POST', '/bucket', { + body: { + id: bucketName, + name: bucketName, + public: false, + }, + expectedStatus: 400, + token, + }) + const stats = await getDatabaseWattStats() + + expect(duplicate.status).toBe(400) + expect(stats.lockedQuery).toBeGreaterThanOrEqual(1) + } finally { + await cleanupRestResources(bucketName, [], client) + } + }) + + it('translates request aborts into Database Watt cancellation', async () => { + await resetDatabaseWattStats() + + const response = await sleepDatabaseWatt() + const stats = await getDatabaseWattStats() + + expect(response).toMatchObject({ code: expect.any(String) }) + expect(stats.cancel).toBeGreaterThanOrEqual(1) + }) + + it('returns typed destination errors through the Database Watt worker', async () => { + const config = getAcceptanceConfig() + + if (!config.tenantId) { + expect(config.tenantId).toBeUndefined() + return + } + + await resetDatabaseWattStats() + const response = await missingDestinationDatabaseWatt() + + expect(response).toMatchObject({ code: 'DESTINATION_UNKNOWN' }) + expect(response.destination).toEqual(expect.stringMatching(/^missing-/)) + }) + + it('handles concurrent Database Watt query load', async () => { + await resetDatabaseWattStats() + + const response = await concurrentQueriesDatabaseWatt() + const stats = await getDatabaseWattStats() + + expect(response).toEqual({ count: 5 }) + expect(stats.query).toBeGreaterThanOrEqual(5) + }) + + it('exercises multitenant destination resolution when the target is multitenant', async () => { + const config = getAcceptanceConfig() + const client = createRestClient() + const token = requireServiceKey(config) + const bucketName = uniqueBucketName('dbwatt-tenant') + + if (!config.tenantId) { + expect(config.tenantId).toBeUndefined() + return + } + + await resetDatabaseWattStats() + try { + await createRestBucket(bucketName, { isPublic: false }) + const bucket = await client.request('GET', `/bucket/${bucketName}`, { + expectedStatus: 200, + token, + }) + const stats = await getDatabaseWattStats() + + expect(bucket.json?.id).toBe(bucketName) + expect(stats.beginTransaction).toBeGreaterThanOrEqual(1) + } finally { + await cleanupRestResources(bucketName, [], client) + } + }) + } +) diff --git a/docs/database-watt-postgresql-scope.md b/docs/database-watt-postgresql-scope.md new file mode 100644 index 000000000..82a7c11bf --- /dev/null +++ b/docs/database-watt-postgresql-scope.md @@ -0,0 +1,18 @@ +# Database Watt PostgreSQL Ownership + +Database Watt owns runtime PostgreSQL access for storage metadata and multitenant master DB queries when the app runs under Watt. + +## Routed Through Database Watt + +- Tenant metadata DB access via `getPostgresConnection()` when Watt messaging is available. +- Multitenant master DB access via `multitenantPgExecutor` when Watt messaging is available. + +## Direct PostgreSQL Access That Remains + +- Direct PostgreSQL fallback for non-Watt/local mode. +- Queue/pg-boss access in `src/internal/queue/database.ts`; queues are intentionally out of this migration for now. +- Migration runner access in `src/internal/database/migrations/migrate.ts`; migrations are intentionally out of scope for Database Watt for now. +- Tests and seeding utilities. +- `pg` type/error imports used to preserve existing public interfaces and error mapping. + +Any new runtime PostgreSQL access should go through Database Watt unless it is explicitly documented here as an exception. diff --git a/package-lock.json b/package-lock.json index 2d4004e16..eb1a15520 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,11 +33,11 @@ "@opentelemetry/instrumentation-runtime-node": "^0.25.0", "@opentelemetry/sdk-metrics": "^2.6.1", "@opentelemetry/sdk-node": "^0.213.0", - "@platformatic/control": "^3.52.0", + "@platformatic/control": "^3.56.0", "@platformatic/flame": "^1.6.0", - "@platformatic/globals": "^3.52.0", - "@platformatic/node": "^3.52.0", - "@platformatic/wattpm-pprof-capture": "^3.52.1", + "@platformatic/globals": "^3.56.0", + "@platformatic/node": "^3.56.0", + "@platformatic/wattpm-pprof-capture": "^3.56.0", "@shopify/semaphore": "^3.0.2", "@smithy/node-http-handler": "^2.3.1", "@tus/file-store": "2.0.0", @@ -77,6 +77,7 @@ "devDependencies": { "@aws-sdk/s3-presigned-post": "^3.1023.0", "@biomejs/biome": "^2.4.4", + "@platformatic/runtime": "^3.56.0", "@types/async-retry": "^1.4.5", "@types/js-yaml": "^4.0.5", "@types/json-bigint": "^1.0.4", @@ -3764,9 +3765,10 @@ } }, "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz", + "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==", + "license": "Apache-2.0", "engines": { "node": ">=8.0.0" } @@ -5298,22 +5300,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/import-in-the-middle": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", @@ -5325,11 +5311,6 @@ "module-details-from-path": "^1.0.3" } }, - "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/require-in-the-middle": { "version": "7.5.2", "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", @@ -8297,9 +8278,10 @@ } }, "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.38.0.tgz", - "integrity": "sha512-kocjix+/sSggfJhwXqClZ3i9Y/MI0fp7b+g7kCRm6psy2dsf8uApTRclwG18h8Avm7C9+fnt+O36PspJ/OzoWg==", + "version": "1.41.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.41.1.tgz", + "integrity": "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==", + "license": "Apache-2.0", "engines": { "node": ">=14" } @@ -8335,118 +8317,80 @@ "license": "MIT" }, "node_modules/@platformatic/basic": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/basic/-/basic-3.52.0.tgz", - "integrity": "sha512-wXn4/Y6kSr11iXOIsEbCBEfWXm23FdK++y8bJ07MqnakERn9Riac2IIXgZm8QHDWbUHWDrQBQBdEqWsg//3luA==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/basic/-/basic-3.56.0.tgz", + "integrity": "sha512-9AaUcp+Kb/NvfzYbDUGx6hIAp1Ns8ltOACSisysJclc411J2qDeYR3/gQjFxzUzSYxC2MtsCmKd6R44+ulzvwA==", "license": "Apache-2.0", "dependencies": { "@fastify/error": "^4.0.0", - "@platformatic/foundation": "3.52.0", - "@platformatic/itc": "3.52.0", - "@platformatic/metrics": "3.52.0", - "@platformatic/telemetry": "3.52.0", + "@platformatic/foundation": "3.56.0", + "@platformatic/globals": "3.56.0", + "@platformatic/itc": "3.56.0", + "@platformatic/metrics": "3.56.0", + "@platformatic/telemetry": "3.56.0", "execa": "^9.3.1", "fast-json-patch": "^3.1.1", "pino": "^9.9.0", "pino-abstract-transport": "^2.0.0", "semver": "^7.6.3", "split2": "^4.2.0", - "undici": "^7.0.0", + "undici": "^7.27.2", "ws": "^8.18.0" }, "engines": { "node": ">=22.19.0" } }, - "node_modules/@platformatic/basic/node_modules/execa": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", - "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^4.0.0", - "cross-spawn": "^7.0.6", - "figures": "^6.1.0", - "get-stream": "^9.0.0", - "human-signals": "^8.0.1", - "is-plain-obj": "^4.1.0", - "is-stream": "^4.0.1", - "npm-run-path": "^6.0.0", - "pretty-ms": "^9.2.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^4.0.0", - "yoctocolors": "^2.1.1" - }, - "engines": { - "node": "^18.19.0 || >=20.5.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/@platformatic/basic/node_modules/get-stream": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", - "license": "MIT", - "dependencies": { - "@sec-ant/readable-stream": "^0.4.1", - "is-stream": "^4.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/@platformatic/basic/node_modules/@fastify/deepmerge": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.2.tgz", + "integrity": "sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" }, - "node_modules/@platformatic/basic/node_modules/human-signals": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", - "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", + "node_modules/@platformatic/basic/node_modules/@platformatic/foundation": { + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/foundation/-/foundation-3.56.0.tgz", + "integrity": "sha512-q0w1DNUS9YUWELXoYDwcicBOxmbqPT9T4zmKHNjEdRPSaD2vf9k50GvSyB8LDFhVxjWekJug6IkPl6P9kaG+wQ==", "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@platformatic/basic/node_modules/is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@platformatic/basic/node_modules/npm-run-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", - "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", - "license": "MIT", "dependencies": { - "path-key": "^4.0.0", - "unicorn-magic": "^0.3.0" + "@fastify/deepmerge": "^2.0.0", + "@fastify/error": "^4.0.0", + "@iarna/toml": "^2.2.5", + "@watchable/unpromise": "^1.0.2", + "ajv": "^8.12.0", + "boring-name-generator": "^1.0.3", + "colorette": "^2.0.19", + "debug": "^4.4.3", + "fast-json-patch": "^3.1.1", + "json5": "^2.2.3", + "leven": "~3.1.0", + "pino": "^9.9.0", + "pino-pretty": "^13.0.0", + "semver": "^7.6.3", + "undici": "7.24.0", + "yaml": "^2.4.1" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=22.19.0" } }, - "node_modules/@platformatic/basic/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "node_modules/@platformatic/basic/node_modules/@platformatic/foundation/node_modules/undici": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.0.tgz", + "integrity": "sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==", "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=20.18.1" } }, "node_modules/@platformatic/basic/node_modules/pino": { @@ -8480,58 +8424,95 @@ "split2": "^4.0.0" } }, - "node_modules/@platformatic/basic/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@platformatic/basic/node_modules/strip-final-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", - "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@platformatic/basic/node_modules/thread-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", - "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz", + "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==", "license": "MIT", "dependencies": { "real-require": "^0.2.0" } }, + "node_modules/@platformatic/basic/node_modules/undici": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/@platformatic/control": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/control/-/control-3.52.0.tgz", - "integrity": "sha512-hZmOnOcoe2/QjrdXUHMrVwb4Nqp/Ba2yXqffz/QCPT1IZ1zAmG28bNYX3PLWFZ+h+TkALU5onHVQjm1Hu7pNzQ==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/control/-/control-3.56.0.tgz", + "integrity": "sha512-tma/OVRXM2pyS4pOoWgRBv/j2B8gSwrhW51F3RNCu8+9H+vllT0EdB0MVwcNkRJLP0LydViyQk0Qml4hbtwmuA==", "license": "Apache-2.0", "dependencies": { "@fastify/error": "^4.0.0", - "@platformatic/foundation": "3.52.0", + "@platformatic/foundation": "3.56.0", "help-me": "^5.0.0", "pino": "^9.9.0", "pino-pretty": "^13.0.0", "table": "^6.8.1", - "undici": "^7.0.0", + "undici": "^7.27.2", "ws": "^8.16.0" }, "engines": { "node": ">=22.19.0" } }, + "node_modules/@platformatic/control/node_modules/@fastify/deepmerge": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.2.tgz", + "integrity": "sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/@platformatic/control/node_modules/@platformatic/foundation": { + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/foundation/-/foundation-3.56.0.tgz", + "integrity": "sha512-q0w1DNUS9YUWELXoYDwcicBOxmbqPT9T4zmKHNjEdRPSaD2vf9k50GvSyB8LDFhVxjWekJug6IkPl6P9kaG+wQ==", + "license": "Apache-2.0", + "dependencies": { + "@fastify/deepmerge": "^2.0.0", + "@fastify/error": "^4.0.0", + "@iarna/toml": "^2.2.5", + "@watchable/unpromise": "^1.0.2", + "ajv": "^8.12.0", + "boring-name-generator": "^1.0.3", + "colorette": "^2.0.19", + "debug": "^4.4.3", + "fast-json-patch": "^3.1.1", + "json5": "^2.2.3", + "leven": "~3.1.0", + "pino": "^9.9.0", + "pino-pretty": "^13.0.0", + "semver": "^7.6.3", + "undici": "7.24.0", + "yaml": "^2.4.1" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/@platformatic/control/node_modules/@platformatic/foundation/node_modules/undici": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.0.tgz", + "integrity": "sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/@platformatic/control/node_modules/pino": { "version": "9.14.0", "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", @@ -8572,6 +8553,15 @@ "real-require": "^0.2.0" } }, + "node_modules/@platformatic/control/node_modules/undici": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/@platformatic/flame": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@platformatic/flame/-/flame-1.6.0.tgz", @@ -8634,29 +8624,6 @@ ], "license": "MIT" }, - "node_modules/@platformatic/foundation/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@platformatic/foundation/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, "node_modules/@platformatic/foundation/node_modules/pino": { "version": "9.14.0", "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", @@ -8707,112 +8674,73 @@ } }, "node_modules/@platformatic/generators": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/generators/-/generators-3.52.0.tgz", - "integrity": "sha512-J+0bs9vce+PGpyzVTwAnVWiXrjEItAYxX7bhzVVX0P0u0BXERi0sy0bklKjBR5tuY16NnteLczuAk0V6xk07/A==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/generators/-/generators-3.56.0.tgz", + "integrity": "sha512-HtTWKfx6gZ6bEmy/gg7QQtmAZCgO8DVyiqtdXleNGaCnkJ/PTgMzJywWk2rMYGDLaKTplJ5o5gzTwftcOgo6Cg==", "license": "Apache-2.0", "dependencies": { "@fastify/error": "^4.0.0", - "@platformatic/foundation": "3.52.0", + "@platformatic/foundation": "3.56.0", "change-case-all": "^2.1.0", "execa": "^9.6.0", "fastify": "^5.7.0", "pino": "^9.9.0", - "undici": "^7.0.0" + "undici": "^7.27.2" }, "engines": { "node": ">=22.19.0" } }, - "node_modules/@platformatic/generators/node_modules/execa": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", - "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^4.0.0", - "cross-spawn": "^7.0.6", - "figures": "^6.1.0", - "get-stream": "^9.0.0", - "human-signals": "^8.0.1", - "is-plain-obj": "^4.1.0", - "is-stream": "^4.0.1", - "npm-run-path": "^6.0.0", - "pretty-ms": "^9.2.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^4.0.0", - "yoctocolors": "^2.1.1" - }, - "engines": { - "node": "^18.19.0 || >=20.5.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/@platformatic/generators/node_modules/get-stream": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", - "license": "MIT", - "dependencies": { - "@sec-ant/readable-stream": "^0.4.1", - "is-stream": "^4.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/@platformatic/generators/node_modules/@fastify/deepmerge": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.2.tgz", + "integrity": "sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" }, - "node_modules/@platformatic/generators/node_modules/human-signals": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", - "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", + "node_modules/@platformatic/generators/node_modules/@platformatic/foundation": { + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/foundation/-/foundation-3.56.0.tgz", + "integrity": "sha512-q0w1DNUS9YUWELXoYDwcicBOxmbqPT9T4zmKHNjEdRPSaD2vf9k50GvSyB8LDFhVxjWekJug6IkPl6P9kaG+wQ==", "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@platformatic/generators/node_modules/is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@platformatic/generators/node_modules/npm-run-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", - "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", - "license": "MIT", "dependencies": { - "path-key": "^4.0.0", - "unicorn-magic": "^0.3.0" + "@fastify/deepmerge": "^2.0.0", + "@fastify/error": "^4.0.0", + "@iarna/toml": "^2.2.5", + "@watchable/unpromise": "^1.0.2", + "ajv": "^8.12.0", + "boring-name-generator": "^1.0.3", + "colorette": "^2.0.19", + "debug": "^4.4.3", + "fast-json-patch": "^3.1.1", + "json5": "^2.2.3", + "leven": "~3.1.0", + "pino": "^9.9.0", + "pino-pretty": "^13.0.0", + "semver": "^7.6.3", + "undici": "7.24.0", + "yaml": "^2.4.1" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=22.19.0" } }, - "node_modules/@platformatic/generators/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "node_modules/@platformatic/generators/node_modules/@platformatic/foundation/node_modules/undici": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.0.tgz", + "integrity": "sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==", "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=20.18.1" } }, "node_modules/@platformatic/generators/node_modules/pino": { @@ -8846,45 +8774,31 @@ "split2": "^4.0.0" } }, - "node_modules/@platformatic/generators/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@platformatic/generators/node_modules/strip-final-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", - "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@platformatic/generators/node_modules/thread-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", - "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz", + "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==", "license": "MIT", "dependencies": { "real-require": "^0.2.0" } }, + "node_modules/@platformatic/generators/node_modules/undici": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/@platformatic/globals": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/globals/-/globals-3.52.0.tgz", - "integrity": "sha512-l/UI72POTtP1kTGBTiwZKqjdjwKFSEfI1f5xDgRyWpowwzax2Ud+75ZQqqyPWf5SmupNUNpV5KEi0zUOuT0ZCg==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/globals/-/globals-3.56.0.tgz", + "integrity": "sha512-FtiUFPoNeUtNEPo5e3o6+ZLlzuMh8ArbXLmJNZf9cnk6zr1otmLA7bV3u02/f1rHhyPx366iAiLfK2E1D6ntTA==", "license": "Apache-2.0", "dependencies": { + "@opentelemetry/api": "^1.9.0", "@platformatic/prom-client": "^1.0.0", "pino": "^9.9.0" }, @@ -8942,12 +8856,14 @@ } }, "node_modules/@platformatic/itc": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/itc/-/itc-3.52.0.tgz", - "integrity": "sha512-XwkT/9K5Mk6Br7xDqH9Zpun73n9GwIiIDEXJXgXPzq0Ek2IvUtaSDhWh02WiCIEvIHHFWXHauTd5olkL8eePbg==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/itc/-/itc-3.56.0.tgz", + "integrity": "sha512-Q5ey6hfsW2DF069hO3pmpdipKj0PR6lxA8fv8QUym4gua+3zMSmF5HxBM51mgvB4XojcaoA8GqchaduYbVzOhw==", "license": "Apache-2.0", "dependencies": { "@fastify/error": "^4.0.0", + "@opentelemetry/api": "^1.9.0", + "@platformatic/globals": "3.56.0", "@watchable/unpromise": "^1.0.2" }, "engines": { @@ -8955,9 +8871,9 @@ } }, "node_modules/@platformatic/metrics": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/metrics/-/metrics-3.52.0.tgz", - "integrity": "sha512-uFCWl1l/0WGtlhmwVQmb4c4ozCZl0xiDuskuZd//xYslhX+UUxs5XGVqFAr4PYJuYQyjooOs22WyXcqX6564xQ==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/metrics/-/metrics-3.56.0.tgz", + "integrity": "sha512-ahCkRK8BslX+9eWZedrdyNUr5t0OAb2zmoXLDa95xtVfibGlIm9cvgke8cC+2dZ11mQP6ipolxnjV8hsfM2czQ==", "license": "Apache-2.0", "dependencies": { "@platformatic/http-metrics": "^0.3.0", @@ -8969,14 +8885,15 @@ } }, "node_modules/@platformatic/node": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/node/-/node-3.52.0.tgz", - "integrity": "sha512-d/F0kmgOHUe2/ZfqQChgbRclCEer+4LZRcFzCiOZyTnbaqs4Ffe2XVRFCemA/EwxvMisgIvKtVF6g5Y82iwc7g==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/node/-/node-3.56.0.tgz", + "integrity": "sha512-Cx20+xeIsrTsE9Y3eb/mxSYKg6p2VhMj/z7g8vD9ox6LtPNkNbJ2J0NPsZBKMz56r8mIIv/SpvQdEk2xWHnf0Q==", "license": "Apache-2.0", "dependencies": { - "@platformatic/basic": "3.52.0", - "@platformatic/foundation": "3.52.0", - "@platformatic/generators": "3.52.0", + "@platformatic/basic": "3.56.0", + "@platformatic/foundation": "3.56.0", + "@platformatic/generators": "3.56.0", + "@platformatic/globals": "3.56.0", "@watchable/unpromise": "^1.0.2", "json5": "^2.2.3", "light-my-request": "^6.0.0" @@ -8985,6 +8902,98 @@ "node": ">=22.19.0" } }, + "node_modules/@platformatic/node/node_modules/@fastify/deepmerge": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.2.tgz", + "integrity": "sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/@platformatic/node/node_modules/@platformatic/foundation": { + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/foundation/-/foundation-3.56.0.tgz", + "integrity": "sha512-q0w1DNUS9YUWELXoYDwcicBOxmbqPT9T4zmKHNjEdRPSaD2vf9k50GvSyB8LDFhVxjWekJug6IkPl6P9kaG+wQ==", + "license": "Apache-2.0", + "dependencies": { + "@fastify/deepmerge": "^2.0.0", + "@fastify/error": "^4.0.0", + "@iarna/toml": "^2.2.5", + "@watchable/unpromise": "^1.0.2", + "ajv": "^8.12.0", + "boring-name-generator": "^1.0.3", + "colorette": "^2.0.19", + "debug": "^4.4.3", + "fast-json-patch": "^3.1.1", + "json5": "^2.2.3", + "leven": "~3.1.0", + "pino": "^9.9.0", + "pino-pretty": "^13.0.0", + "semver": "^7.6.3", + "undici": "7.24.0", + "yaml": "^2.4.1" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/@platformatic/node/node_modules/@platformatic/foundation/node_modules/undici": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.0.tgz", + "integrity": "sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/@platformatic/node/node_modules/pino": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", + "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==", + "license": "MIT", + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/@platformatic/node/node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/@platformatic/node/node_modules/thread-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz", + "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, "node_modules/@platformatic/prom-client": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@platformatic/prom-client/-/prom-client-1.0.0.tgz", @@ -9016,18 +9025,19 @@ } }, "node_modules/@platformatic/promotel/node_modules/undici": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz", - "integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.26.0.tgz", + "integrity": "sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==", "license": "MIT", "engines": { "node": ">=18.17" } }, "node_modules/@platformatic/runtime": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/runtime/-/runtime-3.52.0.tgz", - "integrity": "sha512-/aC8MafEm6dornRlPZoaLlPGHfs/K1JLHgdg1zoC/yg6DpPfo/6MopD2hEb9Hm3aHdTJolmSZ77yzpS2sOes9Q==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/runtime/-/runtime-3.56.0.tgz", + "integrity": "sha512-BB1vZpxyHNmWGbtFNp2vrrNpvomPeyJT3YX313rLb1GvykWfPIUNozNsJsKVVfLPRPAgtW6jE2f4XMFyIW7XHQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@fastify/accepts": "^5.0.0", @@ -9035,13 +9045,14 @@ "@fastify/error": "^4.0.0", "@fastify/websocket": "^11.0.0", "@opentelemetry/api": "^1.9.0", - "@platformatic/basic": "3.52.0", - "@platformatic/foundation": "3.52.0", - "@platformatic/generators": "3.52.0", - "@platformatic/itc": "3.52.0", - "@platformatic/metrics": "3.52.0", + "@platformatic/basic": "3.56.0", + "@platformatic/foundation": "3.56.0", + "@platformatic/generators": "3.56.0", + "@platformatic/globals": "3.56.0", + "@platformatic/itc": "3.56.0", + "@platformatic/metrics": "3.56.0", "@platformatic/prom-client": "^1.0.0", - "@platformatic/telemetry": "3.52.0", + "@platformatic/telemetry": "3.56.0", "@platformatic/undici-cache-memory": "^0.8.1", "@watchable/unpromise": "^1.0.2", "change-case-all": "^2.1.0", @@ -9055,12 +9066,12 @@ "help-me": "^5.0.0", "minimist": "^1.2.8", "pino": "^10.1.0", - "pino-opentelemetry-transport": "^2.0.0", + "pino-opentelemetry-transport": "^3.0.0", "pino-pretty": "^13.0.0", "semgrator": "^0.3.0", "sonic-boom": "^4.2.0", "systeminformation": "^5.27.11", - "undici": "^7.0.0", + "undici": "^7.27.2", "undici-thread-interceptor": "^1.3.1", "ws": "^8.16.0" }, @@ -9068,31 +9079,141 @@ "node": ">=22.19.0" } }, - "node_modules/@platformatic/runtime/node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "license": "MIT" - }, - "node_modules/@platformatic/telemetry": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/telemetry/-/telemetry-3.52.0.tgz", - "integrity": "sha512-QVdy0L0mDnRRhO5w1PJVMaZyx0TluLrN6pe8Lpsu7qBkfoAhxplGMDfxrscu7yXhnNur4X4U4IGGk0Vm5yiDkA==", - "license": "Apache-2.0", - "dependencies": { - "@fastify/swagger": "^9.5.1", - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/core": "^2.0.1", - "@opentelemetry/exporter-trace-otlp-proto": "^0.203.0", - "@opentelemetry/exporter-zipkin": "^2.0.1", - "@opentelemetry/instrumentation": "^0.203.0", - "@opentelemetry/instrumentation-http": "^0.203.0", - "@opentelemetry/instrumentation-undici": "^0.14.0", - "@opentelemetry/resources": "^2.0.1", - "@opentelemetry/sdk-node": "^0.203.0", - "@opentelemetry/sdk-trace-base": "^2.0.1", - "@opentelemetry/semantic-conventions": "1.36.0", - "@platformatic/foundation": "3.52.0", + "node_modules/@platformatic/runtime/node_modules/@fastify/deepmerge": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.2.tgz", + "integrity": "sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/@platformatic/runtime/node_modules/@platformatic/foundation": { + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/foundation/-/foundation-3.56.0.tgz", + "integrity": "sha512-q0w1DNUS9YUWELXoYDwcicBOxmbqPT9T4zmKHNjEdRPSaD2vf9k50GvSyB8LDFhVxjWekJug6IkPl6P9kaG+wQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@fastify/deepmerge": "^2.0.0", + "@fastify/error": "^4.0.0", + "@iarna/toml": "^2.2.5", + "@watchable/unpromise": "^1.0.2", + "ajv": "^8.12.0", + "boring-name-generator": "^1.0.3", + "colorette": "^2.0.19", + "debug": "^4.4.3", + "fast-json-patch": "^3.1.1", + "json5": "^2.2.3", + "leven": "~3.1.0", + "pino": "^9.9.0", + "pino-pretty": "^13.0.0", + "semver": "^7.6.3", + "undici": "7.24.0", + "yaml": "^2.4.1" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/@platformatic/runtime/node_modules/@platformatic/foundation/node_modules/pino": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", + "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/@platformatic/runtime/node_modules/@platformatic/foundation/node_modules/undici": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.0.tgz", + "integrity": "sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/@platformatic/runtime/node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@platformatic/runtime/node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/@platformatic/runtime/node_modules/thread-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz", + "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/@platformatic/runtime/node_modules/undici": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/@platformatic/telemetry": { + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/telemetry/-/telemetry-3.56.0.tgz", + "integrity": "sha512-UG0t8t0r03E7xX1rnM8oKejey5bh87j9bS/EsGqBf42Cr73UuRJmGmL+EbuL8bOF6G9UA88NrWMPgHXzOq67RQ==", + "license": "Apache-2.0", + "dependencies": { + "@fastify/swagger": "^9.5.1", + "@opentelemetry/api": "1.9.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/exporter-trace-otlp-proto": "0.218.0", + "@opentelemetry/exporter-zipkin": "2.7.1", + "@opentelemetry/instrumentation": "0.218.0", + "@opentelemetry/instrumentation-http": "0.218.0", + "@opentelemetry/instrumentation-undici": "0.28.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-node": "0.218.0", + "@opentelemetry/sdk-trace-base": "2.7.1", + "@opentelemetry/semantic-conventions": "1.41.1", + "@platformatic/foundation": "3.56.0", + "@platformatic/globals": "3.56.0", "fast-uri": "^3.0.6", "fastify-plugin": "^5.0.1" }, @@ -9100,10 +9221,26 @@ "node": ">=22.19.0" } }, + "node_modules/@platformatic/telemetry/node_modules/@fastify/deepmerge": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.2.tgz", + "integrity": "sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/api-logs": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz", - "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.218.0.tgz", + "integrity": "sha512-fmEWp5kXlGEc3i/lR698Hz41DfGyN4Tbe4g7L1AxSc7fF8Xeh/FQ9Quqpa9dVA413Q1Ad43QOLzU4JoXgbFPWw==", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.3.0" @@ -9112,26 +9249,27 @@ "node": ">=8.0.0" } }, - "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/context-async-hooks": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.0.1.tgz", - "integrity": "sha512-XuY23lSI3d4PEqKA+7SLtAgwqIfc6E/E9eAQWLN1vlpC53ybO3o6jW4BsXo1xvz9lYyyWItfQDDLzezER01mCw==", + "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/configuration": { + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/configuration/-/configuration-0.218.0.tgz", + "integrity": "sha512-W8wIz7H2R1pufR5jfjb3gU2XkMpm2x/7b1RJcsuzvd70Il/rWWE+g5/Od7hQKrxRTSrTrOWlru101PWXz5I1EQ==", "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "yaml": "^2.0.0" + }, "engines": { "node": "^18.19.0 || >=20.6.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@opentelemetry/api": "^1.9.0" } }, - "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/core": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz", - "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==", + "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/context-async-hooks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.7.1.tgz", + "integrity": "sha512-OPFBYuXEn1E4ja3Y6eeA7O+ZnLBNcXTV5Cgsn1VaqBZ6hC5FnpZPLBNme1LJY8ZtF4aOujPKFoeWN4ik487KuQ==", "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, "engines": { "node": "^18.19.0 || >=20.6.0" }, @@ -9140,17 +9278,17 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/exporter-logs-otlp-grpc": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.203.0.tgz", - "integrity": "sha512-g/2Y2noc/l96zmM+g0LdeuyYKINyBwN6FJySoU15LHPLcMN/1a0wNk2SegwKcxrRdE7Xsm7fkIR5n6XFe3QpPw==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.218.0.tgz", + "integrity": "sha512-hoxrNH1l/Xy6F9WTJ5IK+6j1r9nQFlPOmrnTlhYHTySdunfXLmUCPv3bQtKYntxag9h3wLYBZQ2HI6FOx+BT2g==", "license": "Apache-2.0", "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/sdk-logs": "0.203.0" + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/sdk-logs": "0.218.0" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9160,16 +9298,16 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/exporter-logs-otlp-http": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.203.0.tgz", - "integrity": "sha512-s0hys1ljqlMTbXx2XiplmMJg9wG570Z5lH7wMvrZX6lcODI56sG4HL03jklF63tBeyNwK2RV1/ntXGo3HgG4Qw==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.218.0.tgz", + "integrity": "sha512-Qx+4rpVHzgg89dawcWRHyt+XRXeLnhFz/qBtvggmjkcgPUdr+NAB0/u/eIPA8yAeJV0J80Vz43JZCh/XFvZFGw==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.203.0", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/sdk-logs": "0.203.0" + "@opentelemetry/api-logs": "0.218.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/sdk-logs": "0.218.0" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9179,18 +9317,18 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/exporter-logs-otlp-proto": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.203.0.tgz", - "integrity": "sha512-nl/7S91MXn5R1aIzoWtMKGvqxgJgepB/sH9qW0rZvZtabnsjbf8OQ1uSx3yogtvLr0GzwD596nQKz2fV7q2RBw==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.218.0.tgz", + "integrity": "sha512-1/noQNsp9gXD75HPzgjBrcF1+XTtry7pFAUfxVEJgg7mPv2AawKQuYkhMmJ8qjxz4Ubc3Y8bwvfxevXsKTq4cg==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.203.0", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-logs": "0.203.0", - "@opentelemetry/sdk-trace-base": "2.0.1" + "@opentelemetry/api-logs": "0.218.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.218.0", + "@opentelemetry/sdk-trace-base": "2.7.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9200,19 +9338,19 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/exporter-metrics-otlp-grpc": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.203.0.tgz", - "integrity": "sha512-FCCj9nVZpumPQSEI57jRAA89hQQgONuoC35Lt+rayWY/mzCAc6BQT7RFyFaZKJ2B7IQ8kYjOCPsF/HGFWjdQkQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.218.0.tgz", + "integrity": "sha512-YapQ9vNMX0NSZF6LK5pWAFfjpJleV2O9uYWfYGeb/5F1Kb9rPGK8tZDMJFa/sOksgdFuflDvYuA0B4qjDB4fjQ==", "license": "Apache-2.0", "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-metrics": "2.0.1" + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.218.0", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9222,16 +9360,16 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/exporter-metrics-otlp-http": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.203.0.tgz", - "integrity": "sha512-HFSW10y8lY6BTZecGNpV3GpoSy7eaO0Z6GATwZasnT4bEsILp8UJXNG5OmEsz4SdwCSYvyCbTJdNbZP3/8LGCQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.218.0.tgz", + "integrity": "sha512-bV7d2OuMpZu2+gAaxUAhzfZ0h3WVZk8ETQUEE3DNSntbTaMpuITjtm8I0rNyHFdm7Ax57K6ty7SgFXlBmOLIvQ==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-metrics": "2.0.1" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9241,17 +9379,17 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/exporter-metrics-otlp-proto": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.203.0.tgz", - "integrity": "sha512-OZnhyd9npU7QbyuHXFEPVm3LnjZYifuKpT3kTnF84mXeEQ84pJJZgyLBpU4FSkSwUkt/zbMyNAI7y5+jYTWGIg==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.218.0.tgz", + "integrity": "sha512-ubLddKjWULhla9YZRCj/rTBeppjJYE4e9w0icx5mTu3eFhWjQzbV75NYjXuIlEG+NJsBl6d+sTFw5Qu+oej4oQ==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-metrics": "2.0.1" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.218.0", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9261,14 +9399,15 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/exporter-prometheus": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.203.0.tgz", - "integrity": "sha512-2jLuNuw5m4sUj/SncDf/mFPabUxMZmmYetx5RKIMIQyPnl6G6ooFzfeE8aXNRf8YD1ZXNlCnRPcISxjveGJHNg==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.218.0.tgz", + "integrity": "sha512-RT5oEyu1kddZJ1vt7/BUo5wV+P7hpNAESsR3dUd3+8deHuX7gWNoCOZn+SfDT+hJHlIJ5h/AxiCLXIrutswDJg==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-metrics": "2.0.1" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9278,18 +9417,18 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/exporter-trace-otlp-grpc": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.203.0.tgz", - "integrity": "sha512-322coOTf81bm6cAA8+ML6A+m4r2xTCdmAZzGNTboPXRzhwPt4JEmovsFAs+grpdarObd68msOJ9FfH3jxM6wqA==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.218.0.tgz", + "integrity": "sha512-3fXxVQEj9TNAFaCi79JeFKfeLd0sDtInaR3gaZDVlzNSPHtz8PZuCV34JKWjD4XXzT20IdMe8IpX6mRVNDA4Tw==", "license": "Apache-2.0", "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-trace-base": "2.0.1" + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9299,16 +9438,16 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/exporter-trace-otlp-http": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.203.0.tgz", - "integrity": "sha512-ZDiaswNYo0yq/cy1bBLJFe691izEJ6IgNmkjm4C6kE9ub/OMQqDXORx2D2j8fzTBTxONyzusbaZlqtfmyqURPw==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.218.0.tgz", + "integrity": "sha512-8dqezsmPhtKitIK/eTipZhYl9EX2/gNQ5zUMhaz3uxEURwfkNf8IPvo6yNfrzbxdtpAOybS/+h7wmIWYqFSpiw==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-trace-base": "2.0.1" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9318,16 +9457,16 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/exporter-trace-otlp-proto": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.203.0.tgz", - "integrity": "sha512-1xwNTJ86L0aJmWRwENCJlH4LULMG2sOXWIVw+Szta4fkqKVY50Eo4HoVKKq6U9QEytrWCr8+zjw0q/ZOeXpcAQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.218.0.tgz", + "integrity": "sha512-r1Msf8SNLRmwh9J6XQ5uh82D7CdDWMNHnPB7LAVHjzut0TkSeKc5KcIvr4SvHvfk/xwN5gxC+VLKQ1k0o8PSPw==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-trace-base": "2.0.1" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9337,14 +9476,14 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/exporter-zipkin": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.0.1.tgz", - "integrity": "sha512-a9eeyHIipfdxzCfc2XPrE+/TI3wmrZUDFtG2RRXHSbZZULAny7SyybSvaDvS77a7iib5MPiAvluwVvbGTsHxsw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.7.1.tgz", + "integrity": "sha512-mfsD9bKAxcKrh5+y08TPodvClBO0CznBE3p79YAGnO81WI4LrdsGA65T53e4iTSbCalW4WaUpkbeJcbpyIUHfg==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-trace-base": "2.0.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { @@ -9355,14 +9494,14 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/instrumentation": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.203.0.tgz", - "integrity": "sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.218.0.tgz", + "integrity": "sha512-mIZil8Es+sYDK5m+DQiwAwF57F14TF2YlEqvIjZ/RQWcxDBwRGsKfdK2Tv65OU9meQKCMzSIFS9mxAcnAb6Bkg==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.203.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1" + "@opentelemetry/api-logs": "0.218.0", + "import-in-the-middle": "^3.0.0", + "require-in-the-middle": "^8.0.0" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9372,13 +9511,13 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/instrumentation-http": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.203.0.tgz", - "integrity": "sha512-y3uQAcCOAwnO6vEuNVocmpVzG3PER6/YZqbPbbffDdJ9te5NkHEkfSMNzlC3+v7KlE+WinPGc3N7MR30G1HY2g==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.218.0.tgz", + "integrity": "sha512-x9djaqdzpT8WAboep1H9nCAQ1E+MMsm08TNfA02TqM3bNNddZeiim+E3KMWVQFaX6JpUy7V0nm/wfN/K2Em+Zw==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/instrumentation": "0.203.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/instrumentation": "0.218.0", "@opentelemetry/semantic-conventions": "^1.29.0", "forwarded-parse": "2.1.2" }, @@ -9390,13 +9529,14 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/instrumentation-undici": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.14.0.tgz", - "integrity": "sha512-2HN+7ztxAReXuxzrtA3WboAKlfP5OsPA57KQn2AdYZbJ3zeRPcLXyW4uO/jpLE6PLm0QRtmeGCmfYpqRlwgSwg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.28.0.tgz", + "integrity": "sha512-7nh4Gw7PhYtQm82FIJtWUhx6iZQJj0bdkKe2RQb3XNIyxu0o9rM1J5Xt083SsG2tCbQZpX9/mlDxhTrK1Z/lVQ==", "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.203.0" + "@opentelemetry/instrumentation": "^0.218.0", + "@opentelemetry/semantic-conventions": "^1.24.0" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9406,13 +9546,13 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.203.0.tgz", - "integrity": "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.218.0.tgz", + "integrity": "sha512-ZwqpkNL5W7RyGJPDZ9g06DvKp8KFTWPJPN12anpMQYSKpTSU0z3EIZuPq9vPGpS8siFyOqDYDAuCwlNO9FqgbA==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-transformer": "0.203.0" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-transformer": "0.218.0" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9422,15 +9562,15 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/otlp-grpc-exporter-base": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.203.0.tgz", - "integrity": "sha512-te0Ze1ueJF+N/UOFl5jElJW4U0pZXQ8QklgSfJ2linHN0JJsuaHG8IabEUi2iqxY8ZBDlSiz1Trfv5JcjWWWwQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.218.0.tgz", + "integrity": "sha512-H/lCGJ536N98VpYJOaWTQOkv4Dx6TnmStK6Rqfu1W7KkFbPAx04hjdYEMZF/YbnHzPUSIK4kM6OE2GKGBTpV9A==", "license": "Apache-2.0", "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0" + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9440,18 +9580,17 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/otlp-transformer": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.203.0.tgz", - "integrity": "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.218.0.tgz", + "integrity": "sha512-CFaKH87WAzjuJ4awowTTLzUvMfaRfiOFG5+qm5S5ncyalRtN4ecQ+YmuANJSCrVPuvZFEkUgKhBPBndxi3rHsQ==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.203.0", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-logs": "0.203.0", - "@opentelemetry/sdk-metrics": "2.0.1", - "@opentelemetry/sdk-trace-base": "2.0.1", - "protobufjs": "^7.3.0" + "@opentelemetry/api-logs": "0.218.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.218.0", + "@opentelemetry/sdk-metrics": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9461,12 +9600,12 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/propagator-b3": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-2.0.1.tgz", - "integrity": "sha512-Hc09CaQ8Tf5AGLmf449H726uRoBNGPBL4bjr7AnnUpzWMvhdn61F78z9qb6IqB737TffBsokGAK1XykFEZ1igw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-2.7.1.tgz", + "integrity": "sha512-RJid6E2CKyeGfKBzXKF21ejabGMHypFkPAh3qZ+NvI+SGjuIye79t3PmiqcDgtRzdKH6ynXzbfslQ8DfpRUg2A==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.0.1" + "@opentelemetry/core": "2.7.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9476,12 +9615,12 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/propagator-jaeger": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.0.1.tgz", - "integrity": "sha512-7PMdPBmGVH2eQNb/AtSJizQNgeNTfh6jQFqys6lfhd6P4r+m/nTh3gKPPpaCXVdRQ+z93vfKk+4UGty390283w==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.7.1.tgz", + "integrity": "sha512-KMjVBHzP4N60bOzxja76M1F1hZZ43lGPga5ix+mkv9+kk1nx9SbkxSvJsMbuVUxdPQmsPTqGShmhN8ulrMOg6Q==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.0.1" + "@opentelemetry/core": "2.7.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9491,12 +9630,12 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/resources": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz", - "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.7.1.tgz", + "integrity": "sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.0.1", + "@opentelemetry/core": "2.7.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { @@ -9507,14 +9646,15 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/sdk-logs": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz", - "integrity": "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.218.0.tgz", + "integrity": "sha512-QvnNdugatFTVCJXH0Mcu7GOOJSylA9j127kIezOE4YwTI4YbowRons2K4WZTv5FMS8T4q9P0NdaRHdkSmeAIag==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.203.0", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/resources": "2.0.1" + "@opentelemetry/api-logs": "0.218.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9524,13 +9664,13 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/sdk-metrics": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz", - "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.7.1.tgz", + "integrity": "sha512-MpDJdkiFDs3Pm1RHO3KByuZbuBdJEXEAkiC0+yJdsZGVCdf1RpHR6n+LHDcS7ffmfrt5kVCzJSCfm4z2C7v0uQ==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/resources": "2.0.1" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9540,32 +9680,35 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/sdk-node": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.203.0.tgz", - "integrity": "sha512-zRMvrZGhGVMvAbbjiNQW3eKzW/073dlrSiAKPVWmkoQzah9wfynpVPeL55f9fVIm0GaBxTLcPeukWGy0/Wj7KQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.218.0.tgz", + "integrity": "sha512-tPMjHrLV5gsfNdYqoRHjeGbCAZBXXD9c1Qo/2ut7VwnUABDNh76xNxrT0SEhkIIJuCN45bbN1vZnYL1gY0IkOg==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.203.0", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/exporter-logs-otlp-grpc": "0.203.0", - "@opentelemetry/exporter-logs-otlp-http": "0.203.0", - "@opentelemetry/exporter-logs-otlp-proto": "0.203.0", - "@opentelemetry/exporter-metrics-otlp-grpc": "0.203.0", - "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", - "@opentelemetry/exporter-metrics-otlp-proto": "0.203.0", - "@opentelemetry/exporter-prometheus": "0.203.0", - "@opentelemetry/exporter-trace-otlp-grpc": "0.203.0", - "@opentelemetry/exporter-trace-otlp-http": "0.203.0", - "@opentelemetry/exporter-trace-otlp-proto": "0.203.0", - "@opentelemetry/exporter-zipkin": "2.0.1", - "@opentelemetry/instrumentation": "0.203.0", - "@opentelemetry/propagator-b3": "2.0.1", - "@opentelemetry/propagator-jaeger": "2.0.1", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-logs": "0.203.0", - "@opentelemetry/sdk-metrics": "2.0.1", - "@opentelemetry/sdk-trace-base": "2.0.1", - "@opentelemetry/sdk-trace-node": "2.0.1", + "@opentelemetry/api-logs": "0.218.0", + "@opentelemetry/configuration": "0.218.0", + "@opentelemetry/context-async-hooks": "2.7.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/exporter-logs-otlp-grpc": "0.218.0", + "@opentelemetry/exporter-logs-otlp-http": "0.218.0", + "@opentelemetry/exporter-logs-otlp-proto": "0.218.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "0.218.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.218.0", + "@opentelemetry/exporter-metrics-otlp-proto": "0.218.0", + "@opentelemetry/exporter-prometheus": "0.218.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.218.0", + "@opentelemetry/exporter-trace-otlp-http": "0.218.0", + "@opentelemetry/exporter-trace-otlp-proto": "0.218.0", + "@opentelemetry/exporter-zipkin": "2.7.1", + "@opentelemetry/instrumentation": "0.218.0", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/propagator-b3": "2.7.1", + "@opentelemetry/propagator-jaeger": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.218.0", + "@opentelemetry/sdk-metrics": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1", + "@opentelemetry/sdk-trace-node": "2.7.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { @@ -9576,13 +9719,13 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/sdk-trace-base": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz", - "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/resources": "2.0.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { @@ -9593,14 +9736,14 @@ } }, "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/sdk-trace-node": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.0.1.tgz", - "integrity": "sha512-UhdbPF19pMpBtCWYP5lHbTogLWx9N0EBxtdagvkn5YtsAnCBZzL7SjktG+ZmupRgifsHMjwUaCCaVmqGfSADmA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.7.1.tgz", + "integrity": "sha512-pCpQxU68lV+I9s9svqMyVu5iHdDDUnqUpSxqwyCU8A9ejEsSnMPCbearwsUO4yk08ZJzAIUCFuReMdVQvHrdvg==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/context-async-hooks": "2.0.1", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/sdk-trace-base": "2.0.1" + "@opentelemetry/context-async-hooks": "2.7.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -9609,84 +9752,133 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@platformatic/telemetry/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.36.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.36.0.tgz", - "integrity": "sha512-TtxJSRD8Ohxp6bKkhrm27JRHAxPczQA7idtcTOMYI+wQRRrfgqxHv1cFbCApcSnNjtXkmzFozn6jQtFrOmbjPQ==", + "node_modules/@platformatic/telemetry/node_modules/@platformatic/foundation": { + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/foundation/-/foundation-3.56.0.tgz", + "integrity": "sha512-q0w1DNUS9YUWELXoYDwcicBOxmbqPT9T4zmKHNjEdRPSaD2vf9k50GvSyB8LDFhVxjWekJug6IkPl6P9kaG+wQ==", "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@platformatic/telemetry/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "@fastify/deepmerge": "^2.0.0", + "@fastify/error": "^4.0.0", + "@iarna/toml": "^2.2.5", + "@watchable/unpromise": "^1.0.2", + "ajv": "^8.12.0", + "boring-name-generator": "^1.0.3", + "colorette": "^2.0.19", + "debug": "^4.4.3", + "fast-json-patch": "^3.1.1", + "json5": "^2.2.3", + "leven": "~3.1.0", + "pino": "^9.9.0", + "pino-pretty": "^13.0.0", + "semver": "^7.6.3", + "undici": "7.24.0", + "yaml": "^2.4.1" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=22.19.0" } }, + "node_modules/@platformatic/telemetry/node_modules/cjs-module-lexer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", + "license": "MIT" + }, "node_modules/@platformatic/telemetry/node_modules/import-in-the-middle": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", - "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-3.0.2.tgz", + "integrity": "sha512-LGLYRl0A2gtyUJb2WDliBHmk6TtlHwdDjxonacZ8QrEs/ZW+YDgNv2QAfjRQWpS8HqvNcq6GGnN6jrOa5FysDQ==", "license": "Apache-2.0", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", - "cjs-module-lexer": "^1.2.2", - "module-details-from-path": "^1.0.3" - } - }, - "node_modules/@platformatic/telemetry/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/@platformatic/telemetry/node_modules/require-in-the-middle": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", - "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.3.5", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.8" + "cjs-module-lexer": "^2.2.0", + "module-details-from-path": "^1.0.4" }, "engines": { - "node": ">=8.6.0" + "node": ">=18" } }, - "node_modules/@platformatic/undici-cache-memory": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@platformatic/undici-cache-memory/-/undici-cache-memory-0.8.4.tgz", - "integrity": "sha512-/JVfPhyUW0GQkmr5lGAGOgh0lpJbTcLG8VB2uNqgNgH1fhPPFAM0l4pLSyeDzpTj2r/GJPLqhzvCgangnSHfoQ==", - "license": "Apache-2.0" - }, - "node_modules/@platformatic/wattpm-pprof-capture": { - "version": "3.52.1", - "resolved": "https://registry.npmjs.org/@platformatic/wattpm-pprof-capture/-/wattpm-pprof-capture-3.52.1.tgz", - "integrity": "sha512-OHcHxSKmDba6RURkN4vwAoCE2H5zJULhhlntKOiJo5MdUK4Z5j8gVXvj/Zee5Nr4QWwYyNq4kwgoGCLLPC5tcw==", - "license": "Apache-2.0", + "node_modules/@platformatic/telemetry/node_modules/pino": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", + "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==", + "license": "MIT", "dependencies": { - "@datadog/pprof": "^5.3.0", - "@fastify/error": "^4.0.0", - "undici": "^7.0.0" + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/@platformatic/telemetry/node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/@platformatic/telemetry/node_modules/thread-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz", + "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/@platformatic/telemetry/node_modules/undici": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.0.tgz", + "integrity": "sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/@platformatic/undici-cache-memory": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/@platformatic/undici-cache-memory/-/undici-cache-memory-0.8.4.tgz", + "integrity": "sha512-/JVfPhyUW0GQkmr5lGAGOgh0lpJbTcLG8VB2uNqgNgH1fhPPFAM0l4pLSyeDzpTj2r/GJPLqhzvCgangnSHfoQ==", + "license": "Apache-2.0" + }, + "node_modules/@platformatic/wattpm-pprof-capture": { + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/wattpm-pprof-capture/-/wattpm-pprof-capture-3.56.0.tgz", + "integrity": "sha512-HHBdd3BkHIIUXVSI587GV7/KvKzKvdn7twoqitIEKHtHgvQIQtPV9MPTir2FMMV4CVThuTSMoY6TXTWPlbLspA==", + "license": "Apache-2.0", + "dependencies": { + "@datadog/pprof": "^5.3.0", + "@fastify/error": "^4.0.0", + "@platformatic/globals": "3.56.0", + "undici": "^7.27.2" }, "engines": { "node": ">=22.19.0" } }, + "node_modules/@platformatic/wattpm-pprof-capture/node_modules/undici": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -12864,11 +13056,12 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -13124,6 +13317,56 @@ "bare-events": "^2.7.0" } }, + "node_modules/execa": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", + "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.6", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.2.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": "^18.19.0 || >=20.5.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/expect-type": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", @@ -13577,6 +13820,34 @@ "node": ">= 0.4" } }, + "node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "license": "MIT", + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream/node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-tsconfig": { "version": "4.7.5", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", @@ -13798,6 +14069,15 @@ "node": ">= 14" } }, + "node_modules/human-signals": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, "node_modules/humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -14737,9 +15017,10 @@ "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==" }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/multistream": { "version": "4.1.0", @@ -14840,6 +15121,34 @@ "node-gyp-build-test": "build-test.js" } }, + "node_modules/npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/oauth4webapi": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.1.tgz", @@ -14924,23 +15233,25 @@ } }, "node_modules/otlp-logger": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/otlp-logger/-/otlp-logger-1.1.13.tgz", - "integrity": "sha512-r53tPnMLprtQSMOJUkj4Az4tR8NL+U+8C7M8BV1ZA9y7cDfAbWQp2mRL/eYS/O786oAi9KnN9hKsZ5cFKNchKw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/otlp-logger/-/otlp-logger-2.1.0.tgz", + "integrity": "sha512-UlhiSefpUsuP6hRWpX9UMje71ehvtAhrgXPUUiiqQ1miSwbjLCG+f1TN/mz7dWiOuhwl+VDKi9j+S8DJYAv5bA==", + "dev": true, "license": "MIT", "dependencies": { - "@opentelemetry/api-logs": "^0.206.0", - "@opentelemetry/exporter-logs-otlp-grpc": "^0.206.0", - "@opentelemetry/exporter-logs-otlp-http": "^0.206.0", - "@opentelemetry/exporter-logs-otlp-proto": "^0.206.0", + "@opentelemetry/api-logs": "^0.217.0", + "@opentelemetry/exporter-logs-otlp-grpc": "^0.217.0", + "@opentelemetry/exporter-logs-otlp-http": "^0.217.0", + "@opentelemetry/exporter-logs-otlp-proto": "^0.217.0", "@opentelemetry/resources": "^2.0.0", - "@opentelemetry/sdk-logs": "^0.206.0" + "@opentelemetry/sdk-logs": "^0.217.0" } }, "node_modules/otlp-logger/node_modules/@opentelemetry/api-logs": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.206.0.tgz", - "integrity": "sha512-yIVDu9jX//nV5wSMLZLdHdb1SKHIMj9k+wQVFtln5Flcgdldz9BkHtavvExQiJqBZg2OpEEJEZmzQazYztdz2A==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.217.0.tgz", + "integrity": "sha512-Cdq0jW2lknrNfrAm92MyEAvpe2cRsKjdnQLHUL6xRA4IVUnsWx6P65E7NcUO0Y+L4w1Aee5iV8FvjSwd+lrs9A==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.3.0" @@ -14949,33 +15260,19 @@ "node": ">=8.0.0" } }, - "node_modules/otlp-logger/node_modules/@opentelemetry/core": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.1.0.tgz", - "integrity": "sha512-RMEtHsxJs/GiHHxYT58IY57UXAQTuUnZVco6ymDEqTNlJKTimM4qPUPVe8InNFyBjhHBEAx4k3Q8LtNayBsbUQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, "node_modules/otlp-logger/node_modules/@opentelemetry/exporter-logs-otlp-grpc": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.206.0.tgz", - "integrity": "sha512-kJKxKBaGwqWop95d6tcluz260IWwIgOG0BH8oVm6429tg8LxY2PJb7Om8d5s+5vOFM8DkUYCnIpn9d/13/RcKQ==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.217.0.tgz", + "integrity": "sha512-vC5S0Dc+noxD86CVtNu1+awCHPA5Kewi1Sg23ps+9lh4YifwsKXh3pe4XTNEKtUJiAcjpJ5dqStGakLbrSE+YQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "2.1.0", - "@opentelemetry/otlp-exporter-base": "0.206.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.206.0", - "@opentelemetry/otlp-transformer": "0.206.0", - "@opentelemetry/sdk-logs": "0.206.0" + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/sdk-logs": "0.217.0" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -14985,16 +15282,17 @@ } }, "node_modules/otlp-logger/node_modules/@opentelemetry/exporter-logs-otlp-http": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.206.0.tgz", - "integrity": "sha512-VWcHEnS+1kN+sQTAdCgSn2anqHPxY1/e52fhpe2mcSnEaXI1srFf3RU5DAu7hzQO6T9DPQzOKG8kc76vCtyYDw==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.217.0.tgz", + "integrity": "sha512-KfLAdt1uilVE+3FxbgVnp2ZrzqbIawzcesnRoi+Kh9ckB5Ld5D8btUgoBvwTbdmuNx1j6b132Wsh72azq+pPNQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.206.0", - "@opentelemetry/core": "2.1.0", - "@opentelemetry/otlp-exporter-base": "0.206.0", - "@opentelemetry/otlp-transformer": "0.206.0", - "@opentelemetry/sdk-logs": "0.206.0" + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/sdk-logs": "0.217.0" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -15004,18 +15302,19 @@ } }, "node_modules/otlp-logger/node_modules/@opentelemetry/exporter-logs-otlp-proto": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.206.0.tgz", - "integrity": "sha512-CsYNXJwkn1qCXJGE+/JvvYucAjL8rpaxa2hnl+tDP6M5E0O3UVa8zG4ZUEebjr5J5Nc32egvslEZx5rgNOp3lQ==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.217.0.tgz", + "integrity": "sha512-Se0GG/ZO24mQTlQj7zprR4pNI0nKe4lPDPBsuJmi6508b9TlZEuUd3EfyuHk6oJxzL7fGyDFYAbxNigQvRP2ZQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.206.0", - "@opentelemetry/core": "2.1.0", - "@opentelemetry/otlp-exporter-base": "0.206.0", - "@opentelemetry/otlp-transformer": "0.206.0", - "@opentelemetry/resources": "2.1.0", - "@opentelemetry/sdk-logs": "0.206.0", - "@opentelemetry/sdk-trace-base": "2.1.0" + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.217.0", + "@opentelemetry/sdk-trace-base": "2.7.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -15025,13 +15324,14 @@ } }, "node_modules/otlp-logger/node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.206.0.tgz", - "integrity": "sha512-Rv54oSNKMHYS5hv+H5EGksfBUtvPQWFTK+Dk6MjJun9tOijCsFJrhRFvAqg5d67TWSMn+ZQYRKIeXh5oLVrpAQ==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.217.0.tgz", + "integrity": "sha512-eYfqnB3UhKu/5frhd1R6+FprKygbhkomuaceMXDyzxbfXB9tKgZOVmjaJ02CkLA6Tdzumxl+e2H+vo2a8jiMPQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.1.0", - "@opentelemetry/otlp-transformer": "0.206.0" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-transformer": "0.217.0" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -15041,15 +15341,16 @@ } }, "node_modules/otlp-logger/node_modules/@opentelemetry/otlp-grpc-exporter-base": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.206.0.tgz", - "integrity": "sha512-IA8EDbrB8OKtidMqErBY8sUc9mh03LOXuNPwp4/rdPrxSt45g1gBuZMovRXdEWfRyKKbF2E7MdipT2m11bs6SQ==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.217.0.tgz", + "integrity": "sha512-7RTAdZuOsCDnsyqTCG4+bDzrfnsWdzkRs7z0AVi/V3tEQx0oKeyc+OuRWYxnRsmaJXgxcmB8vb/lfxn58Dj6Ag==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "2.1.0", - "@opentelemetry/otlp-exporter-base": "0.206.0", - "@opentelemetry/otlp-transformer": "0.206.0" + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -15059,18 +15360,19 @@ } }, "node_modules/otlp-logger/node_modules/@opentelemetry/otlp-transformer": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.206.0.tgz", - "integrity": "sha512-Li2Cik1WnmNbU2mmTnw7DxvRiXhMcnAuTfAclP8y/zy7h5+GrLDpTZ+Z0XUs+Q3MLkb/h3ry4uFrC/z+2a6X7g==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.217.0.tgz", + "integrity": "sha512-MKK8UHKFUOGAvbZRWh90MhwHG+Fxm6OROBdjKPCF+HQobjuJ/Kuf8Chs8CR45X1aqotxrMj7OxTdsXe8sXuGVA==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.206.0", - "@opentelemetry/core": "2.1.0", - "@opentelemetry/resources": "2.1.0", - "@opentelemetry/sdk-logs": "0.206.0", - "@opentelemetry/sdk-metrics": "2.1.0", - "@opentelemetry/sdk-trace-base": "2.1.0", - "protobufjs": "^7.3.0" + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.217.0", + "@opentelemetry/sdk-metrics": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1", + "protobufjs": "8.0.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -15080,12 +15382,13 @@ } }, "node_modules/otlp-logger/node_modules/@opentelemetry/resources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.1.0.tgz", - "integrity": "sha512-1CJjf3LCvoefUOgegxi8h6r4B/wLSzInyhGP2UmIBYNlo4Qk5CZ73e1eEyWmfXvFtm1ybkmfb2DqWvspsYLrWw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.7.1.tgz", + "integrity": "sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.1.0", + "@opentelemetry/core": "2.7.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { @@ -15096,14 +15399,16 @@ } }, "node_modules/otlp-logger/node_modules/@opentelemetry/sdk-logs": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.206.0.tgz", - "integrity": "sha512-SQ2yTmqe4Mw9RI3a/glVkfjWPsXh6LySvnljXubiZq4zu+UP8NMJt2j82ZsYb+KpD7Eu+/41/7qlJnjdeVjz7Q==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.217.0.tgz", + "integrity": "sha512-BB+PcHItcZDL63dPMW+mJvwN9rk37wuIDjRxbVlg6pPDvDR/7GL7UJHbGsllgoggOoTimsKgENaWPoGch/oE1A==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.206.0", - "@opentelemetry/core": "2.1.0", - "@opentelemetry/resources": "2.1.0" + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -15113,13 +15418,14 @@ } }, "node_modules/otlp-logger/node_modules/@opentelemetry/sdk-metrics": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.1.0.tgz", - "integrity": "sha512-J9QX459mzqHLL9Y6FZ4wQPRZG4TOpMCyPOh6mkr/humxE1W2S3Bvf4i75yiMW9uyed2Kf5rxmLhTm/UK8vNkAw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.7.1.tgz", + "integrity": "sha512-MpDJdkiFDs3Pm1RHO3KByuZbuBdJEXEAkiC0+yJdsZGVCdf1RpHR6n+LHDcS7ffmfrt5kVCzJSCfm4z2C7v0uQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.1.0", - "@opentelemetry/resources": "2.1.0" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" @@ -15129,13 +15435,14 @@ } }, "node_modules/otlp-logger/node_modules/@opentelemetry/sdk-trace-base": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.1.0.tgz", - "integrity": "sha512-uTX9FBlVQm4S2gVQO1sb5qyBLq/FPjbp+tmGoxu4tIgtYGmBYB44+KX/725RFDe30yBSaA9Ml9fqphe1hbUyLQ==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.1.0", - "@opentelemetry/resources": "2.1.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { @@ -15145,6 +15452,31 @@ "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, + "node_modules/otlp-logger/node_modules/protobufjs": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.0.1.tgz", + "integrity": "sha512-NWWCCscLjs+cOKF/s/XVNFRW7Yih0fdH+9brffR5NZCy8k42yRdl5KlWKMVXuI1vfCoy4o1z80XR/W/QUb3V3w==", + "dev": true, + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/parse-ms": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", @@ -15423,12 +15755,13 @@ } }, "node_modules/pino-opentelemetry-transport": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pino-opentelemetry-transport/-/pino-opentelemetry-transport-2.0.0.tgz", - "integrity": "sha512-tWoq02WEtnCWfr63Co1n0sGlDpkBz2YUovSAsSBv/+jwKUIn/PjxwRileGViKrH/K3e+oc71nGl6yUdgQlrVkg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pino-opentelemetry-transport/-/pino-opentelemetry-transport-3.0.0.tgz", + "integrity": "sha512-t/fH23X+/pSSaUTdD7hq8FbT5BtTnUvXDojxKNVGX/auDPpDshG58t2yxFr2cmMgpQetIKBCcsH3KmcJXJJ5cQ==", + "dev": true, "license": "MIT", "dependencies": { - "otlp-logger": "^1.1.4", + "otlp-logger": "^2.0.0", "pino-abstract-transport": "^3.0.0" }, "peerDependencies": { @@ -15439,6 +15772,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", + "dev": true, "license": "MIT", "dependencies": { "split2": "^4.0.0" @@ -15896,27 +16230,6 @@ "node": ">=9.3.0 || >=8.10.0 <9.0.0" } }, - "node_modules/require-in-the-middle/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/require-in-the-middle/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -16437,6 +16750,18 @@ "node": ">=8" } }, + "node_modules/strip-final-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strnum": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.3.tgz", @@ -17564,431 +17889,1457 @@ "node": ">=22.19.0" } }, - "node_modules/wattpm/node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "license": "MIT" - }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "license": "MIT", + "node_modules/wattpm/node_modules/@opentelemetry/api-logs": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz", + "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, "engines": { - "node": ">= 8" + "node": ">=8.0.0" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "node_modules/wattpm/node_modules/@opentelemetry/context-async-hooks": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.0.1.tgz", + "integrity": "sha512-XuY23lSI3d4PEqKA+7SLtAgwqIfc6E/E9eAQWLN1vlpC53ybO3o6jW4BsXo1xvz9lYyyWItfQDDLzezER01mCw==", + "license": "Apache-2.0", + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/wattpm/node_modules/@opentelemetry/core": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz", + "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==", + "license": "Apache-2.0", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { - "node": ">= 8" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, - "license": "MIT", + "node_modules/wattpm/node_modules/@opentelemetry/exporter-logs-otlp-grpc": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.203.0.tgz", + "integrity": "sha512-g/2Y2noc/l96zmM+g0LdeuyYKINyBwN6FJySoU15LHPLcMN/1a0wNk2SegwKcxrRdE7Xsm7fkIR5n6XFe3QpPw==", + "license": "Apache-2.0", "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/sdk-logs": "0.203.0" }, "engines": { - "node": ">=8" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/wattpm/node_modules/@opentelemetry/exporter-logs-otlp-http": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.203.0.tgz", + "integrity": "sha512-s0hys1ljqlMTbXx2XiplmMJg9wG570Z5lH7wMvrZX6lcODI56sG4HL03jklF63tBeyNwK2RV1/ntXGo3HgG4Qw==", + "license": "Apache-2.0", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "@opentelemetry/api-logs": "0.203.0", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/sdk-logs": "0.203.0" }, "engines": { - "node": ">=10" + "node": "^18.19.0 || >=20.6.0" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/wattpm/node_modules/@opentelemetry/exporter-logs-otlp-proto": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.203.0.tgz", + "integrity": "sha512-nl/7S91MXn5R1aIzoWtMKGvqxgJgepB/sH9qW0rZvZtabnsjbf8OQ1uSx3yogtvLr0GzwD596nQKz2fV7q2RBw==", + "license": "Apache-2.0", "dependencies": { - "color-convert": "^2.0.1" + "@opentelemetry/api-logs": "0.203.0", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-logs": "0.203.0", + "@opentelemetry/sdk-trace-base": "2.0.1" }, "engines": { - "node": ">=8" + "node": "^18.19.0 || >=20.6.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" + "node_modules/wattpm/node_modules/@opentelemetry/exporter-metrics-otlp-grpc": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.203.0.tgz", + "integrity": "sha512-FCCj9nVZpumPQSEI57jRAA89hQQgONuoC35Lt+rayWY/mzCAc6BQT7RFyFaZKJ2B7IQ8kYjOCPsF/HGFWjdQkQ==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-metrics": "2.0.1" }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "engines": { + "node": "^18.19.0 || >=20.6.0" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/xml2js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", - "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "node_modules/wattpm/node_modules/@opentelemetry/exporter-metrics-otlp-http": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.203.0.tgz", + "integrity": "sha512-HFSW10y8lY6BTZecGNpV3GpoSy7eaO0Z6GATwZasnT4bEsILp8UJXNG5OmEsz4SdwCSYvyCbTJdNbZP3/8LGCQ==", + "license": "Apache-2.0", "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-metrics": "2.0.1" }, "engines": { - "node": ">=4.0.0" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "node_modules/wattpm/node_modules/@opentelemetry/exporter-metrics-otlp-proto": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.203.0.tgz", + "integrity": "sha512-OZnhyd9npU7QbyuHXFEPVm3LnjZYifuKpT3kTnF84mXeEQ84pJJZgyLBpU4FSkSwUkt/zbMyNAI7y5+jYTWGIg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-metrics": "2.0.1" + }, "engines": { - "node": ">=4.0" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "node_modules/wattpm/node_modules/@opentelemetry/exporter-prometheus": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.203.0.tgz", + "integrity": "sha512-2jLuNuw5m4sUj/SncDf/mFPabUxMZmmYetx5RKIMIQyPnl6G6ooFzfeE8aXNRf8YD1ZXNlCnRPcISxjveGJHNg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-metrics": "2.0.1" + }, "engines": { - "node": ">=0.4" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "node_modules/wattpm/node_modules/@opentelemetry/exporter-trace-otlp-grpc": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.203.0.tgz", + "integrity": "sha512-322coOTf81bm6cAA8+ML6A+m4r2xTCdmAZzGNTboPXRzhwPt4JEmovsFAs+grpdarObd68msOJ9FfH3jxM6wqA==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1" + }, "engines": { - "node": ">=10" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true - }, - "node_modules/yaml": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", - "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", - "bin": { - "yaml": "bin.mjs" + "node_modules/wattpm/node_modules/@opentelemetry/exporter-trace-otlp-http": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.203.0.tgz", + "integrity": "sha512-ZDiaswNYo0yq/cy1bBLJFe691izEJ6IgNmkjm4C6kE9ub/OMQqDXORx2D2j8fzTBTxONyzusbaZlqtfmyqURPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1" }, "engines": { - "node": ">= 14.6" + "node": "^18.19.0 || >=20.6.0" }, - "funding": { - "url": "https://github.com/sponsors/eemeli" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "node_modules/wattpm/node_modules/@opentelemetry/exporter-trace-otlp-proto": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.203.0.tgz", + "integrity": "sha512-1xwNTJ86L0aJmWRwENCJlH4LULMG2sOXWIVw+Szta4fkqKVY50Eo4HoVKKq6U9QEytrWCr8+zjw0q/ZOeXpcAQ==", + "license": "Apache-2.0", "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1" }, "engines": { - "node": ">=12" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "node_modules/wattpm/node_modules/@opentelemetry/exporter-zipkin": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.0.1.tgz", + "integrity": "sha512-a9eeyHIipfdxzCfc2XPrE+/TI3wmrZUDFtG2RRXHSbZZULAny7SyybSvaDvS77a7iib5MPiAvluwVvbGTsHxsw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, "engines": { - "node": ">=12" + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/yoctocolors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", - "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", - "license": "MIT", + "node_modules/wattpm/node_modules/@opentelemetry/instrumentation": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.203.0.tgz", + "integrity": "sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.203.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1" + }, "engines": { - "node": ">=18" + "node": "^18.19.0 || >=20.6.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@aws-crypto/crc32": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", - "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", - "requires": { - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^2.6.2" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "@aws-crypto/crc32c": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", - "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", - "requires": { - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^2.6.2" + "node_modules/wattpm/node_modules/@opentelemetry/instrumentation-http": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.203.0.tgz", + "integrity": "sha512-y3uQAcCOAwnO6vEuNVocmpVzG3PER6/YZqbPbbffDdJ9te5NkHEkfSMNzlC3+v7KlE+WinPGc3N7MR30G1HY2g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/instrumentation": "0.203.0", + "@opentelemetry/semantic-conventions": "^1.29.0", + "forwarded-parse": "2.1.2" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "@aws-crypto/sha1-browser": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", - "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", - "requires": { - "@aws-crypto/supports-web-crypto": "^5.2.0", - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.6.2" - }, + "node_modules/wattpm/node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.14.0.tgz", + "integrity": "sha512-2HN+7ztxAReXuxzrtA3WboAKlfP5OsPA57KQn2AdYZbJ3zeRPcLXyW4uO/jpLE6PLm0QRtmeGCmfYpqRlwgSwg==", + "license": "Apache-2.0", "dependencies": { - "@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", - "requires": { - "tslib": "^2.6.2" - } - }, - "@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", - "requires": { - "@smithy/is-array-buffer": "^2.2.0", - "tslib": "^2.6.2" - } - }, - "@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", - "requires": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" - } - } + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.203.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.7.0" } }, - "@aws-crypto/sha256-browser": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", - "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", - "requires": { - "@aws-crypto/sha256-js": "^5.2.0", - "@aws-crypto/supports-web-crypto": "^5.2.0", - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.6.2" - }, + "node_modules/wattpm/node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.203.0.tgz", + "integrity": "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==", + "license": "Apache-2.0", "dependencies": { - "@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", - "requires": { - "tslib": "^2.6.2" - } - }, - "@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", - "requires": { - "@smithy/is-array-buffer": "^2.2.0", - "tslib": "^2.6.2" - } - }, - "@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", - "requires": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" - } - } + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-transformer": "0.203.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "@aws-crypto/sha256-js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", - "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", - "requires": { - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^2.6.2" + "node_modules/wattpm/node_modules/@opentelemetry/otlp-grpc-exporter-base": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.203.0.tgz", + "integrity": "sha512-te0Ze1ueJF+N/UOFl5jElJW4U0pZXQ8QklgSfJ2linHN0JJsuaHG8IabEUi2iqxY8ZBDlSiz1Trfv5JcjWWWwQ==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "@aws-crypto/supports-web-crypto": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", - "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", - "requires": { - "tslib": "^2.6.2" + "node_modules/wattpm/node_modules/@opentelemetry/otlp-transformer": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.203.0.tgz", + "integrity": "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.203.0", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-logs": "0.203.0", + "@opentelemetry/sdk-metrics": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1", + "protobufjs": "^7.3.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "@aws-crypto/util": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", - "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", - "requires": { - "@aws-sdk/types": "^3.222.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.6.2" + "node_modules/wattpm/node_modules/@opentelemetry/propagator-b3": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-2.0.1.tgz", + "integrity": "sha512-Hc09CaQ8Tf5AGLmf449H726uRoBNGPBL4bjr7AnnUpzWMvhdn61F78z9qb6IqB737TffBsokGAK1XykFEZ1igw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/wattpm/node_modules/@opentelemetry/propagator-jaeger": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.0.1.tgz", + "integrity": "sha512-7PMdPBmGVH2eQNb/AtSJizQNgeNTfh6jQFqys6lfhd6P4r+m/nTh3gKPPpaCXVdRQ+z93vfKk+4UGty390283w==", + "license": "Apache-2.0", "dependencies": { - "@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", - "requires": { - "tslib": "^2.6.2" - } - }, - "@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", - "requires": { - "@smithy/is-array-buffer": "^2.2.0", - "tslib": "^2.6.2" - } - }, - "@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", - "requires": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" - } - } + "@opentelemetry/core": "2.0.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "@aws-sdk/client-ecs": { - "version": "3.1041.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ecs/-/client-ecs-3.1041.0.tgz", - "integrity": "sha512-ws/U2a5SE1vaJdbGqSO76V3Q/fz5HxQOI1R2OGhGSCTKmMrtUVTgPQNMqLsqX8RYsy16y5N504WoUbqSxBaNrw==", - "requires": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.974.8", - "@aws-sdk/credential-provider-node": "^3.972.39", - "@aws-sdk/middleware-host-header": "^3.972.10", - "@aws-sdk/middleware-logger": "^3.972.10", - "@aws-sdk/middleware-recursion-detection": "^3.972.11", - "@aws-sdk/middleware-user-agent": "^3.972.38", - "@aws-sdk/region-config-resolver": "^3.972.13", - "@aws-sdk/types": "^3.973.8", - "@aws-sdk/util-endpoints": "^3.996.8", - "@aws-sdk/util-user-agent-browser": "^3.972.10", - "@aws-sdk/util-user-agent-node": "^3.973.24", - "@smithy/config-resolver": "^4.4.17", - "@smithy/core": "^3.23.17", - "@smithy/fetch-http-handler": "^5.3.17", - "@smithy/hash-node": "^4.2.14", - "@smithy/invalid-dependency": "^4.2.14", - "@smithy/middleware-content-length": "^4.2.14", - "@smithy/middleware-endpoint": "^4.4.32", - "@smithy/middleware-retry": "^4.5.7", - "@smithy/middleware-serde": "^4.2.20", - "@smithy/middleware-stack": "^4.2.14", - "@smithy/node-config-provider": "^4.3.14", - "@smithy/node-http-handler": "^4.6.1", - "@smithy/protocol-http": "^5.3.14", - "@smithy/smithy-client": "^4.12.13", - "@smithy/types": "^4.14.1", - "@smithy/url-parser": "^4.2.14", - "@smithy/util-base64": "^4.3.2", - "@smithy/util-body-length-browser": "^4.2.2", - "@smithy/util-body-length-node": "^4.2.3", - "@smithy/util-defaults-mode-browser": "^4.3.49", - "@smithy/util-defaults-mode-node": "^4.2.54", - "@smithy/util-endpoints": "^3.4.2", - "@smithy/util-middleware": "^4.2.14", - "@smithy/util-retry": "^4.3.6", - "@smithy/util-utf8": "^4.2.2", - "@smithy/util-waiter": "^4.3.0", - "tslib": "^2.6.2" + "node_modules/wattpm/node_modules/@opentelemetry/resources": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz", + "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/wattpm/node_modules/@opentelemetry/sdk-logs": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz", + "integrity": "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==", + "license": "Apache-2.0", "dependencies": { - "@smithy/is-array-buffer": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.2.tgz", - "integrity": "sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==", - "requires": { - "tslib": "^2.6.2" - } - }, + "@opentelemetry/api-logs": "0.203.0", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.10.0" + } + }, + "node_modules/wattpm/node_modules/@opentelemetry/sdk-metrics": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz", + "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.9.0 <1.10.0" + } + }, + "node_modules/wattpm/node_modules/@opentelemetry/sdk-node": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.203.0.tgz", + "integrity": "sha512-zRMvrZGhGVMvAbbjiNQW3eKzW/073dlrSiAKPVWmkoQzah9wfynpVPeL55f9fVIm0GaBxTLcPeukWGy0/Wj7KQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.203.0", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/exporter-logs-otlp-grpc": "0.203.0", + "@opentelemetry/exporter-logs-otlp-http": "0.203.0", + "@opentelemetry/exporter-logs-otlp-proto": "0.203.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "0.203.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", + "@opentelemetry/exporter-metrics-otlp-proto": "0.203.0", + "@opentelemetry/exporter-prometheus": "0.203.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.203.0", + "@opentelemetry/exporter-trace-otlp-http": "0.203.0", + "@opentelemetry/exporter-trace-otlp-proto": "0.203.0", + "@opentelemetry/exporter-zipkin": "2.0.1", + "@opentelemetry/instrumentation": "0.203.0", + "@opentelemetry/propagator-b3": "2.0.1", + "@opentelemetry/propagator-jaeger": "2.0.1", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-logs": "0.203.0", + "@opentelemetry/sdk-metrics": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1", + "@opentelemetry/sdk-trace-node": "2.0.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/wattpm/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz", + "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/wattpm/node_modules/@opentelemetry/sdk-trace-node": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.0.1.tgz", + "integrity": "sha512-UhdbPF19pMpBtCWYP5lHbTogLWx9N0EBxtdagvkn5YtsAnCBZzL7SjktG+ZmupRgifsHMjwUaCCaVmqGfSADmA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/context-async-hooks": "2.0.1", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/wattpm/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.36.0.tgz", + "integrity": "sha512-TtxJSRD8Ohxp6bKkhrm27JRHAxPczQA7idtcTOMYI+wQRRrfgqxHv1cFbCApcSnNjtXkmzFozn6jQtFrOmbjPQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/wattpm/node_modules/@platformatic/basic": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@platformatic/basic/-/basic-3.52.0.tgz", + "integrity": "sha512-wXn4/Y6kSr11iXOIsEbCBEfWXm23FdK++y8bJ07MqnakERn9Riac2IIXgZm8QHDWbUHWDrQBQBdEqWsg//3luA==", + "license": "Apache-2.0", + "dependencies": { + "@fastify/error": "^4.0.0", + "@platformatic/foundation": "3.52.0", + "@platformatic/itc": "3.52.0", + "@platformatic/metrics": "3.52.0", + "@platformatic/telemetry": "3.52.0", + "execa": "^9.3.1", + "fast-json-patch": "^3.1.1", + "pino": "^9.9.0", + "pino-abstract-transport": "^2.0.0", + "semver": "^7.6.3", + "split2": "^4.2.0", + "undici": "^7.0.0", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/wattpm/node_modules/@platformatic/control": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@platformatic/control/-/control-3.52.0.tgz", + "integrity": "sha512-hZmOnOcoe2/QjrdXUHMrVwb4Nqp/Ba2yXqffz/QCPT1IZ1zAmG28bNYX3PLWFZ+h+TkALU5onHVQjm1Hu7pNzQ==", + "license": "Apache-2.0", + "dependencies": { + "@fastify/error": "^4.0.0", + "@platformatic/foundation": "3.52.0", + "help-me": "^5.0.0", + "pino": "^9.9.0", + "pino-pretty": "^13.0.0", + "table": "^6.8.1", + "undici": "^7.0.0", + "ws": "^8.16.0" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/wattpm/node_modules/@platformatic/generators": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@platformatic/generators/-/generators-3.52.0.tgz", + "integrity": "sha512-J+0bs9vce+PGpyzVTwAnVWiXrjEItAYxX7bhzVVX0P0u0BXERi0sy0bklKjBR5tuY16NnteLczuAk0V6xk07/A==", + "license": "Apache-2.0", + "dependencies": { + "@fastify/error": "^4.0.0", + "@platformatic/foundation": "3.52.0", + "change-case-all": "^2.1.0", + "execa": "^9.6.0", + "fastify": "^5.7.0", + "pino": "^9.9.0", + "undici": "^7.0.0" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/wattpm/node_modules/@platformatic/itc": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@platformatic/itc/-/itc-3.52.0.tgz", + "integrity": "sha512-XwkT/9K5Mk6Br7xDqH9Zpun73n9GwIiIDEXJXgXPzq0Ek2IvUtaSDhWh02WiCIEvIHHFWXHauTd5olkL8eePbg==", + "license": "Apache-2.0", + "dependencies": { + "@fastify/error": "^4.0.0", + "@watchable/unpromise": "^1.0.2" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/wattpm/node_modules/@platformatic/metrics": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@platformatic/metrics/-/metrics-3.52.0.tgz", + "integrity": "sha512-uFCWl1l/0WGtlhmwVQmb4c4ozCZl0xiDuskuZd//xYslhX+UUxs5XGVqFAr4PYJuYQyjooOs22WyXcqX6564xQ==", + "license": "Apache-2.0", + "dependencies": { + "@platformatic/http-metrics": "^0.3.0", + "@platformatic/prom-client": "^1.0.0", + "@platformatic/promotel": "^0.1.0" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/wattpm/node_modules/@platformatic/runtime": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@platformatic/runtime/-/runtime-3.52.0.tgz", + "integrity": "sha512-/aC8MafEm6dornRlPZoaLlPGHfs/K1JLHgdg1zoC/yg6DpPfo/6MopD2hEb9Hm3aHdTJolmSZ77yzpS2sOes9Q==", + "license": "Apache-2.0", + "dependencies": { + "@fastify/accepts": "^5.0.0", + "@fastify/basic-auth": "^6.0.0", + "@fastify/error": "^4.0.0", + "@fastify/websocket": "^11.0.0", + "@opentelemetry/api": "^1.9.0", + "@platformatic/basic": "3.52.0", + "@platformatic/foundation": "3.52.0", + "@platformatic/generators": "3.52.0", + "@platformatic/itc": "3.52.0", + "@platformatic/metrics": "3.52.0", + "@platformatic/prom-client": "^1.0.0", + "@platformatic/telemetry": "3.52.0", + "@platformatic/undici-cache-memory": "^0.8.1", + "@watchable/unpromise": "^1.0.2", + "change-case-all": "^2.1.0", + "close-with-grace": "^2.3.0", + "colorette": "^2.0.20", + "cron": "^4.1.0", + "debounce": "^2.0.0", + "fastest-levenshtein": "^1.0.16", + "fastify": "^5.7.0", + "graphql": "^16.8.1", + "help-me": "^5.0.0", + "minimist": "^1.2.8", + "pino": "^10.1.0", + "pino-opentelemetry-transport": "^2.0.0", + "pino-pretty": "^13.0.0", + "semgrator": "^0.3.0", + "sonic-boom": "^4.2.0", + "systeminformation": "^5.27.11", + "undici": "^7.0.0", + "undici-thread-interceptor": "^1.3.1", + "ws": "^8.16.0" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/wattpm/node_modules/@platformatic/runtime/node_modules/pino": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/pino/-/pino-10.3.1.tgz", + "integrity": "sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==", + "license": "MIT", + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^3.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^4.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/wattpm/node_modules/@platformatic/runtime/node_modules/pino-abstract-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", + "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/wattpm/node_modules/@platformatic/runtime/node_modules/pino-opentelemetry-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-opentelemetry-transport/-/pino-opentelemetry-transport-2.0.0.tgz", + "integrity": "sha512-tWoq02WEtnCWfr63Co1n0sGlDpkBz2YUovSAsSBv/+jwKUIn/PjxwRileGViKrH/K3e+oc71nGl6yUdgQlrVkg==", + "license": "MIT", + "dependencies": { + "otlp-logger": "^1.1.4", + "pino-abstract-transport": "^3.0.0" + }, + "peerDependencies": { + "pino": "^10.0.0" + } + }, + "node_modules/wattpm/node_modules/@platformatic/runtime/node_modules/thread-stream": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.2.0.tgz", + "integrity": "sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ==", + "license": "MIT", + "dependencies": { + "real-require": "^1.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/wattpm/node_modules/@platformatic/runtime/node_modules/thread-stream/node_modules/real-require": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-1.0.0.tgz", + "integrity": "sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g==", + "license": "MIT" + }, + "node_modules/wattpm/node_modules/@platformatic/telemetry": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@platformatic/telemetry/-/telemetry-3.52.0.tgz", + "integrity": "sha512-QVdy0L0mDnRRhO5w1PJVMaZyx0TluLrN6pe8Lpsu7qBkfoAhxplGMDfxrscu7yXhnNur4X4U4IGGk0Vm5yiDkA==", + "license": "Apache-2.0", + "dependencies": { + "@fastify/swagger": "^9.5.1", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/core": "^2.0.1", + "@opentelemetry/exporter-trace-otlp-proto": "^0.203.0", + "@opentelemetry/exporter-zipkin": "^2.0.1", + "@opentelemetry/instrumentation": "^0.203.0", + "@opentelemetry/instrumentation-http": "^0.203.0", + "@opentelemetry/instrumentation-undici": "^0.14.0", + "@opentelemetry/resources": "^2.0.1", + "@opentelemetry/sdk-node": "^0.203.0", + "@opentelemetry/sdk-trace-base": "^2.0.1", + "@opentelemetry/semantic-conventions": "1.36.0", + "@platformatic/foundation": "3.52.0", + "fast-uri": "^3.0.6", + "fastify-plugin": "^5.0.1" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/wattpm/node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" + }, + "node_modules/wattpm/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/wattpm/node_modules/otlp-logger": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/otlp-logger/-/otlp-logger-1.1.13.tgz", + "integrity": "sha512-r53tPnMLprtQSMOJUkj4Az4tR8NL+U+8C7M8BV1ZA9y7cDfAbWQp2mRL/eYS/O786oAi9KnN9hKsZ5cFKNchKw==", + "license": "MIT", + "dependencies": { + "@opentelemetry/api-logs": "^0.206.0", + "@opentelemetry/exporter-logs-otlp-grpc": "^0.206.0", + "@opentelemetry/exporter-logs-otlp-http": "^0.206.0", + "@opentelemetry/exporter-logs-otlp-proto": "^0.206.0", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/sdk-logs": "^0.206.0" + } + }, + "node_modules/wattpm/node_modules/otlp-logger/node_modules/@opentelemetry/api-logs": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.206.0.tgz", + "integrity": "sha512-yIVDu9jX//nV5wSMLZLdHdb1SKHIMj9k+wQVFtln5Flcgdldz9BkHtavvExQiJqBZg2OpEEJEZmzQazYztdz2A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/wattpm/node_modules/otlp-logger/node_modules/@opentelemetry/core": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.1.0.tgz", + "integrity": "sha512-RMEtHsxJs/GiHHxYT58IY57UXAQTuUnZVco6ymDEqTNlJKTimM4qPUPVe8InNFyBjhHBEAx4k3Q8LtNayBsbUQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/wattpm/node_modules/otlp-logger/node_modules/@opentelemetry/exporter-logs-otlp-grpc": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.206.0.tgz", + "integrity": "sha512-kJKxKBaGwqWop95d6tcluz260IWwIgOG0BH8oVm6429tg8LxY2PJb7Om8d5s+5vOFM8DkUYCnIpn9d/13/RcKQ==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.1.0", + "@opentelemetry/otlp-exporter-base": "0.206.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.206.0", + "@opentelemetry/otlp-transformer": "0.206.0", + "@opentelemetry/sdk-logs": "0.206.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/wattpm/node_modules/otlp-logger/node_modules/@opentelemetry/exporter-logs-otlp-http": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.206.0.tgz", + "integrity": "sha512-VWcHEnS+1kN+sQTAdCgSn2anqHPxY1/e52fhpe2mcSnEaXI1srFf3RU5DAu7hzQO6T9DPQzOKG8kc76vCtyYDw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.206.0", + "@opentelemetry/core": "2.1.0", + "@opentelemetry/otlp-exporter-base": "0.206.0", + "@opentelemetry/otlp-transformer": "0.206.0", + "@opentelemetry/sdk-logs": "0.206.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/wattpm/node_modules/otlp-logger/node_modules/@opentelemetry/exporter-logs-otlp-proto": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.206.0.tgz", + "integrity": "sha512-CsYNXJwkn1qCXJGE+/JvvYucAjL8rpaxa2hnl+tDP6M5E0O3UVa8zG4ZUEebjr5J5Nc32egvslEZx5rgNOp3lQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.206.0", + "@opentelemetry/core": "2.1.0", + "@opentelemetry/otlp-exporter-base": "0.206.0", + "@opentelemetry/otlp-transformer": "0.206.0", + "@opentelemetry/resources": "2.1.0", + "@opentelemetry/sdk-logs": "0.206.0", + "@opentelemetry/sdk-trace-base": "2.1.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/wattpm/node_modules/otlp-logger/node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.206.0.tgz", + "integrity": "sha512-Rv54oSNKMHYS5hv+H5EGksfBUtvPQWFTK+Dk6MjJun9tOijCsFJrhRFvAqg5d67TWSMn+ZQYRKIeXh5oLVrpAQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.1.0", + "@opentelemetry/otlp-transformer": "0.206.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/wattpm/node_modules/otlp-logger/node_modules/@opentelemetry/otlp-grpc-exporter-base": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.206.0.tgz", + "integrity": "sha512-IA8EDbrB8OKtidMqErBY8sUc9mh03LOXuNPwp4/rdPrxSt45g1gBuZMovRXdEWfRyKKbF2E7MdipT2m11bs6SQ==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.1.0", + "@opentelemetry/otlp-exporter-base": "0.206.0", + "@opentelemetry/otlp-transformer": "0.206.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/wattpm/node_modules/otlp-logger/node_modules/@opentelemetry/otlp-transformer": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.206.0.tgz", + "integrity": "sha512-Li2Cik1WnmNbU2mmTnw7DxvRiXhMcnAuTfAclP8y/zy7h5+GrLDpTZ+Z0XUs+Q3MLkb/h3ry4uFrC/z+2a6X7g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.206.0", + "@opentelemetry/core": "2.1.0", + "@opentelemetry/resources": "2.1.0", + "@opentelemetry/sdk-logs": "0.206.0", + "@opentelemetry/sdk-metrics": "2.1.0", + "@opentelemetry/sdk-trace-base": "2.1.0", + "protobufjs": "^7.3.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/wattpm/node_modules/otlp-logger/node_modules/@opentelemetry/resources": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.1.0.tgz", + "integrity": "sha512-1CJjf3LCvoefUOgegxi8h6r4B/wLSzInyhGP2UmIBYNlo4Qk5CZ73e1eEyWmfXvFtm1ybkmfb2DqWvspsYLrWw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.1.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/wattpm/node_modules/otlp-logger/node_modules/@opentelemetry/sdk-logs": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.206.0.tgz", + "integrity": "sha512-SQ2yTmqe4Mw9RI3a/glVkfjWPsXh6LySvnljXubiZq4zu+UP8NMJt2j82ZsYb+KpD7Eu+/41/7qlJnjdeVjz7Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.206.0", + "@opentelemetry/core": "2.1.0", + "@opentelemetry/resources": "2.1.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.10.0" + } + }, + "node_modules/wattpm/node_modules/otlp-logger/node_modules/@opentelemetry/sdk-metrics": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.1.0.tgz", + "integrity": "sha512-J9QX459mzqHLL9Y6FZ4wQPRZG4TOpMCyPOh6mkr/humxE1W2S3Bvf4i75yiMW9uyed2Kf5rxmLhTm/UK8vNkAw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.1.0", + "@opentelemetry/resources": "2.1.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.9.0 <1.10.0" + } + }, + "node_modules/wattpm/node_modules/otlp-logger/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.1.0.tgz", + "integrity": "sha512-uTX9FBlVQm4S2gVQO1sb5qyBLq/FPjbp+tmGoxu4tIgtYGmBYB44+KX/725RFDe30yBSaA9Ml9fqphe1hbUyLQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.1.0", + "@opentelemetry/resources": "2.1.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/wattpm/node_modules/pino": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", + "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==", + "license": "MIT", + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/wattpm/node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/wattpm/node_modules/require-in-the-middle": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", + "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/wattpm/node_modules/thread-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz", + "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, + "node_modules/yaml": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yoctocolors": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", + "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "requires": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "requires": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "requires": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "requires": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "requires": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + } + } + } + }, + "@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "requires": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "requires": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "requires": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + } + } + } + }, + "@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "requires": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "requires": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "requires": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "requires": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + } + } + } + }, + "@aws-sdk/client-ecs": { + "version": "3.1041.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ecs/-/client-ecs-3.1041.0.tgz", + "integrity": "sha512-ws/U2a5SE1vaJdbGqSO76V3Q/fz5HxQOI1R2OGhGSCTKmMrtUVTgPQNMqLsqX8RYsy16y5N504WoUbqSxBaNrw==", + "requires": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.8", + "@aws-sdk/credential-provider-node": "^3.972.39", + "@aws-sdk/middleware-host-header": "^3.972.10", + "@aws-sdk/middleware-logger": "^3.972.10", + "@aws-sdk/middleware-recursion-detection": "^3.972.11", + "@aws-sdk/middleware-user-agent": "^3.972.38", + "@aws-sdk/region-config-resolver": "^3.972.13", + "@aws-sdk/types": "^3.973.8", + "@aws-sdk/util-endpoints": "^3.996.8", + "@aws-sdk/util-user-agent-browser": "^3.972.10", + "@aws-sdk/util-user-agent-node": "^3.973.24", + "@smithy/config-resolver": "^4.4.17", + "@smithy/core": "^3.23.17", + "@smithy/fetch-http-handler": "^5.3.17", + "@smithy/hash-node": "^4.2.14", + "@smithy/invalid-dependency": "^4.2.14", + "@smithy/middleware-content-length": "^4.2.14", + "@smithy/middleware-endpoint": "^4.4.32", + "@smithy/middleware-retry": "^4.5.7", + "@smithy/middleware-serde": "^4.2.20", + "@smithy/middleware-stack": "^4.2.14", + "@smithy/node-config-provider": "^4.3.14", + "@smithy/node-http-handler": "^4.6.1", + "@smithy/protocol-http": "^5.3.14", + "@smithy/smithy-client": "^4.12.13", + "@smithy/types": "^4.14.1", + "@smithy/url-parser": "^4.2.14", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-body-length-node": "^4.2.3", + "@smithy/util-defaults-mode-browser": "^4.3.49", + "@smithy/util-defaults-mode-node": "^4.2.54", + "@smithy/util-endpoints": "^3.4.2", + "@smithy/util-middleware": "^4.2.14", + "@smithy/util-retry": "^4.3.6", + "@smithy/util-utf8": "^4.2.2", + "@smithy/util-waiter": "^4.3.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.2.tgz", + "integrity": "sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==", + "requires": { + "tslib": "^2.6.2" + } + }, "@smithy/node-http-handler": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.6.1.tgz", @@ -20254,9 +21605,9 @@ } }, "@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz", + "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==" }, "@opentelemetry/api-logs": { "version": "0.214.0", @@ -21286,14 +22637,6 @@ "require-in-the-middle": "^7.1.1" } }, - "debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "requires": { - "ms": "^2.1.3" - } - }, "import-in-the-middle": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", @@ -21305,11 +22648,6 @@ "module-details-from-path": "^1.0.3" } }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, "require-in-the-middle": { "version": "7.5.2", "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", @@ -23321,9 +24659,9 @@ } }, "@opentelemetry/semantic-conventions": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.38.0.tgz", - "integrity": "sha512-kocjix+/sSggfJhwXqClZ3i9Y/MI0fp7b+g7kCRm6psy2dsf8uApTRclwG18h8Avm7C9+fnt+O36PspJ/OzoWg==" + "version": "1.41.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.41.1.tgz", + "integrity": "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==" }, "@opentelemetry/sql-common": { "version": "0.41.2", @@ -23345,77 +24683,61 @@ "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==" }, "@platformatic/basic": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/basic/-/basic-3.52.0.tgz", - "integrity": "sha512-wXn4/Y6kSr11iXOIsEbCBEfWXm23FdK++y8bJ07MqnakERn9Riac2IIXgZm8QHDWbUHWDrQBQBdEqWsg//3luA==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/basic/-/basic-3.56.0.tgz", + "integrity": "sha512-9AaUcp+Kb/NvfzYbDUGx6hIAp1Ns8ltOACSisysJclc411J2qDeYR3/gQjFxzUzSYxC2MtsCmKd6R44+ulzvwA==", "requires": { "@fastify/error": "^4.0.0", - "@platformatic/foundation": "3.52.0", - "@platformatic/itc": "3.52.0", - "@platformatic/metrics": "3.52.0", - "@platformatic/telemetry": "3.52.0", + "@platformatic/foundation": "3.56.0", + "@platformatic/globals": "3.56.0", + "@platformatic/itc": "3.56.0", + "@platformatic/metrics": "3.56.0", + "@platformatic/telemetry": "3.56.0", "execa": "^9.3.1", "fast-json-patch": "^3.1.1", "pino": "^9.9.0", "pino-abstract-transport": "^2.0.0", "semver": "^7.6.3", "split2": "^4.2.0", - "undici": "^7.0.0", + "undici": "^7.27.2", "ws": "^8.18.0" }, "dependencies": { - "execa": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", - "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", - "requires": { - "@sindresorhus/merge-streams": "^4.0.0", - "cross-spawn": "^7.0.6", - "figures": "^6.1.0", - "get-stream": "^9.0.0", - "human-signals": "^8.0.1", - "is-plain-obj": "^4.1.0", - "is-stream": "^4.0.1", - "npm-run-path": "^6.0.0", - "pretty-ms": "^9.2.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^4.0.0", - "yoctocolors": "^2.1.1" - } - }, - "get-stream": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", - "requires": { - "@sec-ant/readable-stream": "^0.4.1", - "is-stream": "^4.0.1" - } - }, - "human-signals": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", - "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==" - }, - "is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==" + "@fastify/deepmerge": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.2.tgz", + "integrity": "sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==" }, - "npm-run-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", - "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", - "requires": { - "path-key": "^4.0.0", - "unicorn-magic": "^0.3.0" + "@platformatic/foundation": { + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/foundation/-/foundation-3.56.0.tgz", + "integrity": "sha512-q0w1DNUS9YUWELXoYDwcicBOxmbqPT9T4zmKHNjEdRPSaD2vf9k50GvSyB8LDFhVxjWekJug6IkPl6P9kaG+wQ==", + "requires": { + "@fastify/deepmerge": "^2.0.0", + "@fastify/error": "^4.0.0", + "@iarna/toml": "^2.2.5", + "@watchable/unpromise": "^1.0.2", + "ajv": "^8.12.0", + "boring-name-generator": "^1.0.3", + "colorette": "^2.0.19", + "debug": "^4.4.3", + "fast-json-patch": "^3.1.1", + "json5": "^2.2.3", + "leven": "~3.1.0", + "pino": "^9.9.0", + "pino-pretty": "^13.0.0", + "semver": "^7.6.3", + "undici": "7.24.0", + "yaml": "^2.4.1" + }, + "dependencies": { + "undici": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.0.tgz", + "integrity": "sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==" + } } }, - "path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==" - }, "pino": { "version": "9.14.0", "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", @@ -23442,41 +24764,71 @@ "split2": "^4.0.0" } }, - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" - }, - "strip-final-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", - "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==" - }, "thread-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", - "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz", + "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==", "requires": { "real-require": "^0.2.0" } + }, + "undici": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==" } } }, "@platformatic/control": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/control/-/control-3.52.0.tgz", - "integrity": "sha512-hZmOnOcoe2/QjrdXUHMrVwb4Nqp/Ba2yXqffz/QCPT1IZ1zAmG28bNYX3PLWFZ+h+TkALU5onHVQjm1Hu7pNzQ==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/control/-/control-3.56.0.tgz", + "integrity": "sha512-tma/OVRXM2pyS4pOoWgRBv/j2B8gSwrhW51F3RNCu8+9H+vllT0EdB0MVwcNkRJLP0LydViyQk0Qml4hbtwmuA==", "requires": { "@fastify/error": "^4.0.0", - "@platformatic/foundation": "3.52.0", + "@platformatic/foundation": "3.56.0", "help-me": "^5.0.0", "pino": "^9.9.0", "pino-pretty": "^13.0.0", "table": "^6.8.1", - "undici": "^7.0.0", + "undici": "^7.27.2", "ws": "^8.16.0" }, "dependencies": { + "@fastify/deepmerge": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.2.tgz", + "integrity": "sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==" + }, + "@platformatic/foundation": { + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/foundation/-/foundation-3.56.0.tgz", + "integrity": "sha512-q0w1DNUS9YUWELXoYDwcicBOxmbqPT9T4zmKHNjEdRPSaD2vf9k50GvSyB8LDFhVxjWekJug6IkPl6P9kaG+wQ==", + "requires": { + "@fastify/deepmerge": "^2.0.0", + "@fastify/error": "^4.0.0", + "@iarna/toml": "^2.2.5", + "@watchable/unpromise": "^1.0.2", + "ajv": "^8.12.0", + "boring-name-generator": "^1.0.3", + "colorette": "^2.0.19", + "debug": "^4.4.3", + "fast-json-patch": "^3.1.1", + "json5": "^2.2.3", + "leven": "~3.1.0", + "pino": "^9.9.0", + "pino-pretty": "^13.0.0", + "semver": "^7.6.3", + "undici": "7.24.0", + "yaml": "^2.4.1" + }, + "dependencies": { + "undici": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.0.tgz", + "integrity": "sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==" + } + } + }, "pino": { "version": "9.14.0", "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", @@ -23510,6 +24862,11 @@ "requires": { "real-require": "^0.2.0" } + }, + "undici": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==" } } }, @@ -23553,19 +24910,6 @@ "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.2.tgz", "integrity": "sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==" }, - "debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "requires": { - "ms": "^2.1.3" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, "pino": { "version": "9.14.0", "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", @@ -23608,71 +24952,54 @@ } }, "@platformatic/generators": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/generators/-/generators-3.52.0.tgz", - "integrity": "sha512-J+0bs9vce+PGpyzVTwAnVWiXrjEItAYxX7bhzVVX0P0u0BXERi0sy0bklKjBR5tuY16NnteLczuAk0V6xk07/A==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/generators/-/generators-3.56.0.tgz", + "integrity": "sha512-HtTWKfx6gZ6bEmy/gg7QQtmAZCgO8DVyiqtdXleNGaCnkJ/PTgMzJywWk2rMYGDLaKTplJ5o5gzTwftcOgo6Cg==", "requires": { "@fastify/error": "^4.0.0", - "@platformatic/foundation": "3.52.0", + "@platformatic/foundation": "3.56.0", "change-case-all": "^2.1.0", "execa": "^9.6.0", "fastify": "^5.7.0", "pino": "^9.9.0", - "undici": "^7.0.0" + "undici": "^7.27.2" }, "dependencies": { - "execa": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", - "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", - "requires": { - "@sindresorhus/merge-streams": "^4.0.0", - "cross-spawn": "^7.0.6", - "figures": "^6.1.0", - "get-stream": "^9.0.0", - "human-signals": "^8.0.1", - "is-plain-obj": "^4.1.0", - "is-stream": "^4.0.1", - "npm-run-path": "^6.0.0", - "pretty-ms": "^9.2.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^4.0.0", - "yoctocolors": "^2.1.1" - } - }, - "get-stream": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", - "requires": { - "@sec-ant/readable-stream": "^0.4.1", - "is-stream": "^4.0.1" - } - }, - "human-signals": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", - "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==" - }, - "is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==" + "@fastify/deepmerge": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.2.tgz", + "integrity": "sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==" }, - "npm-run-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", - "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", - "requires": { - "path-key": "^4.0.0", - "unicorn-magic": "^0.3.0" + "@platformatic/foundation": { + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/foundation/-/foundation-3.56.0.tgz", + "integrity": "sha512-q0w1DNUS9YUWELXoYDwcicBOxmbqPT9T4zmKHNjEdRPSaD2vf9k50GvSyB8LDFhVxjWekJug6IkPl6P9kaG+wQ==", + "requires": { + "@fastify/deepmerge": "^2.0.0", + "@fastify/error": "^4.0.0", + "@iarna/toml": "^2.2.5", + "@watchable/unpromise": "^1.0.2", + "ajv": "^8.12.0", + "boring-name-generator": "^1.0.3", + "colorette": "^2.0.19", + "debug": "^4.4.3", + "fast-json-patch": "^3.1.1", + "json5": "^2.2.3", + "leven": "~3.1.0", + "pino": "^9.9.0", + "pino-pretty": "^13.0.0", + "semver": "^7.6.3", + "undici": "7.24.0", + "yaml": "^2.4.1" + }, + "dependencies": { + "undici": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.0.tgz", + "integrity": "sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==" + } } }, - "path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==" - }, "pino": { "version": "9.14.0", "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", @@ -23699,31 +25026,27 @@ "split2": "^4.0.0" } }, - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" - }, - "strip-final-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", - "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==" - }, "thread-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", - "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz", + "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==", "requires": { "real-require": "^0.2.0" } + }, + "undici": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==" } } }, "@platformatic/globals": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/globals/-/globals-3.52.0.tgz", - "integrity": "sha512-l/UI72POTtP1kTGBTiwZKqjdjwKFSEfI1f5xDgRyWpowwzax2Ud+75ZQqqyPWf5SmupNUNpV5KEi0zUOuT0ZCg==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/globals/-/globals-3.56.0.tgz", + "integrity": "sha512-FtiUFPoNeUtNEPo5e3o6+ZLlzuMh8ArbXLmJNZf9cnk6zr1otmLA7bV3u02/f1rHhyPx366iAiLfK2E1D6ntTA==", "requires": { + "@opentelemetry/api": "^1.9.0", "@platformatic/prom-client": "^1.0.0", "pino": "^9.9.0" }, @@ -23773,18 +25096,20 @@ } }, "@platformatic/itc": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/itc/-/itc-3.52.0.tgz", - "integrity": "sha512-XwkT/9K5Mk6Br7xDqH9Zpun73n9GwIiIDEXJXgXPzq0Ek2IvUtaSDhWh02WiCIEvIHHFWXHauTd5olkL8eePbg==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/itc/-/itc-3.56.0.tgz", + "integrity": "sha512-Q5ey6hfsW2DF069hO3pmpdipKj0PR6lxA8fv8QUym4gua+3zMSmF5HxBM51mgvB4XojcaoA8GqchaduYbVzOhw==", "requires": { "@fastify/error": "^4.0.0", + "@opentelemetry/api": "^1.9.0", + "@platformatic/globals": "3.56.0", "@watchable/unpromise": "^1.0.2" } }, "@platformatic/metrics": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/metrics/-/metrics-3.52.0.tgz", - "integrity": "sha512-uFCWl1l/0WGtlhmwVQmb4c4ozCZl0xiDuskuZd//xYslhX+UUxs5XGVqFAr4PYJuYQyjooOs22WyXcqX6564xQ==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/metrics/-/metrics-3.56.0.tgz", + "integrity": "sha512-ahCkRK8BslX+9eWZedrdyNUr5t0OAb2zmoXLDa95xtVfibGlIm9cvgke8cC+2dZ11mQP6ipolxnjV8hsfM2czQ==", "requires": { "@platformatic/http-metrics": "^0.3.0", "@platformatic/prom-client": "^1.0.0", @@ -23792,16 +25117,88 @@ } }, "@platformatic/node": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/node/-/node-3.52.0.tgz", - "integrity": "sha512-d/F0kmgOHUe2/ZfqQChgbRclCEer+4LZRcFzCiOZyTnbaqs4Ffe2XVRFCemA/EwxvMisgIvKtVF6g5Y82iwc7g==", - "requires": { - "@platformatic/basic": "3.52.0", - "@platformatic/foundation": "3.52.0", - "@platformatic/generators": "3.52.0", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/node/-/node-3.56.0.tgz", + "integrity": "sha512-Cx20+xeIsrTsE9Y3eb/mxSYKg6p2VhMj/z7g8vD9ox6LtPNkNbJ2J0NPsZBKMz56r8mIIv/SpvQdEk2xWHnf0Q==", + "requires": { + "@platformatic/basic": "3.56.0", + "@platformatic/foundation": "3.56.0", + "@platformatic/generators": "3.56.0", + "@platformatic/globals": "3.56.0", "@watchable/unpromise": "^1.0.2", "json5": "^2.2.3", "light-my-request": "^6.0.0" + }, + "dependencies": { + "@fastify/deepmerge": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.2.tgz", + "integrity": "sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==" + }, + "@platformatic/foundation": { + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/foundation/-/foundation-3.56.0.tgz", + "integrity": "sha512-q0w1DNUS9YUWELXoYDwcicBOxmbqPT9T4zmKHNjEdRPSaD2vf9k50GvSyB8LDFhVxjWekJug6IkPl6P9kaG+wQ==", + "requires": { + "@fastify/deepmerge": "^2.0.0", + "@fastify/error": "^4.0.0", + "@iarna/toml": "^2.2.5", + "@watchable/unpromise": "^1.0.2", + "ajv": "^8.12.0", + "boring-name-generator": "^1.0.3", + "colorette": "^2.0.19", + "debug": "^4.4.3", + "fast-json-patch": "^3.1.1", + "json5": "^2.2.3", + "leven": "~3.1.0", + "pino": "^9.9.0", + "pino-pretty": "^13.0.0", + "semver": "^7.6.3", + "undici": "7.24.0", + "yaml": "^2.4.1" + }, + "dependencies": { + "undici": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.0.tgz", + "integrity": "sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==" + } + } + }, + "pino": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", + "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==", + "requires": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + } + }, + "pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "requires": { + "split2": "^4.0.0" + } + }, + "thread-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz", + "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==", + "requires": { + "real-require": "^0.2.0" + } + } } }, "@platformatic/prom-client": { @@ -23824,29 +25221,31 @@ }, "dependencies": { "undici": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz", - "integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==" + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.26.0.tgz", + "integrity": "sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==" } } }, "@platformatic/runtime": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/runtime/-/runtime-3.52.0.tgz", - "integrity": "sha512-/aC8MafEm6dornRlPZoaLlPGHfs/K1JLHgdg1zoC/yg6DpPfo/6MopD2hEb9Hm3aHdTJolmSZ77yzpS2sOes9Q==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/runtime/-/runtime-3.56.0.tgz", + "integrity": "sha512-BB1vZpxyHNmWGbtFNp2vrrNpvomPeyJT3YX313rLb1GvykWfPIUNozNsJsKVVfLPRPAgtW6jE2f4XMFyIW7XHQ==", + "dev": true, "requires": { "@fastify/accepts": "^5.0.0", "@fastify/basic-auth": "^6.0.0", "@fastify/error": "^4.0.0", "@fastify/websocket": "^11.0.0", "@opentelemetry/api": "^1.9.0", - "@platformatic/basic": "3.52.0", - "@platformatic/foundation": "3.52.0", - "@platformatic/generators": "3.52.0", - "@platformatic/itc": "3.52.0", - "@platformatic/metrics": "3.52.0", + "@platformatic/basic": "3.56.0", + "@platformatic/foundation": "3.56.0", + "@platformatic/generators": "3.56.0", + "@platformatic/globals": "3.56.0", + "@platformatic/itc": "3.56.0", + "@platformatic/metrics": "3.56.0", "@platformatic/prom-client": "^1.0.0", - "@platformatic/telemetry": "3.52.0", + "@platformatic/telemetry": "3.56.0", "@platformatic/undici-cache-memory": "^0.8.1", "@watchable/unpromise": "^1.0.2", "change-case-all": "^2.1.0", @@ -23860,400 +25259,533 @@ "help-me": "^5.0.0", "minimist": "^1.2.8", "pino": "^10.1.0", - "pino-opentelemetry-transport": "^2.0.0", + "pino-opentelemetry-transport": "^3.0.0", "pino-pretty": "^13.0.0", "semgrator": "^0.3.0", "sonic-boom": "^4.2.0", "systeminformation": "^5.27.11", - "undici": "^7.0.0", + "undici": "^7.27.2", "undici-thread-interceptor": "^1.3.1", "ws": "^8.16.0" }, "dependencies": { + "@fastify/deepmerge": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.2.tgz", + "integrity": "sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==", + "dev": true + }, + "@platformatic/foundation": { + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/foundation/-/foundation-3.56.0.tgz", + "integrity": "sha512-q0w1DNUS9YUWELXoYDwcicBOxmbqPT9T4zmKHNjEdRPSaD2vf9k50GvSyB8LDFhVxjWekJug6IkPl6P9kaG+wQ==", + "dev": true, + "requires": { + "@fastify/deepmerge": "^2.0.0", + "@fastify/error": "^4.0.0", + "@iarna/toml": "^2.2.5", + "@watchable/unpromise": "^1.0.2", + "ajv": "^8.12.0", + "boring-name-generator": "^1.0.3", + "colorette": "^2.0.19", + "debug": "^4.4.3", + "fast-json-patch": "^3.1.1", + "json5": "^2.2.3", + "leven": "~3.1.0", + "pino": "^9.9.0", + "pino-pretty": "^13.0.0", + "semver": "^7.6.3", + "undici": "7.24.0", + "yaml": "^2.4.1" + }, + "dependencies": { + "pino": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", + "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==", + "dev": true, + "requires": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + } + }, + "undici": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.0.tgz", + "integrity": "sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==", + "dev": true + } + } + }, "colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "dev": true, + "requires": { + "split2": "^4.0.0" + } + }, + "thread-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz", + "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==", + "dev": true, + "requires": { + "real-require": "^0.2.0" + } + }, + "undici": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==", + "dev": true } } }, "@platformatic/telemetry": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@platformatic/telemetry/-/telemetry-3.52.0.tgz", - "integrity": "sha512-QVdy0L0mDnRRhO5w1PJVMaZyx0TluLrN6pe8Lpsu7qBkfoAhxplGMDfxrscu7yXhnNur4X4U4IGGk0Vm5yiDkA==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/telemetry/-/telemetry-3.56.0.tgz", + "integrity": "sha512-UG0t8t0r03E7xX1rnM8oKejey5bh87j9bS/EsGqBf42Cr73UuRJmGmL+EbuL8bOF6G9UA88NrWMPgHXzOq67RQ==", "requires": { "@fastify/swagger": "^9.5.1", - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/core": "^2.0.1", - "@opentelemetry/exporter-trace-otlp-proto": "^0.203.0", - "@opentelemetry/exporter-zipkin": "^2.0.1", - "@opentelemetry/instrumentation": "^0.203.0", - "@opentelemetry/instrumentation-http": "^0.203.0", - "@opentelemetry/instrumentation-undici": "^0.14.0", - "@opentelemetry/resources": "^2.0.1", - "@opentelemetry/sdk-node": "^0.203.0", - "@opentelemetry/sdk-trace-base": "^2.0.1", - "@opentelemetry/semantic-conventions": "1.36.0", - "@platformatic/foundation": "3.52.0", + "@opentelemetry/api": "1.9.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/exporter-trace-otlp-proto": "0.218.0", + "@opentelemetry/exporter-zipkin": "2.7.1", + "@opentelemetry/instrumentation": "0.218.0", + "@opentelemetry/instrumentation-http": "0.218.0", + "@opentelemetry/instrumentation-undici": "0.28.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-node": "0.218.0", + "@opentelemetry/sdk-trace-base": "2.7.1", + "@opentelemetry/semantic-conventions": "1.41.1", + "@platformatic/foundation": "3.56.0", + "@platformatic/globals": "3.56.0", "fast-uri": "^3.0.6", "fastify-plugin": "^5.0.1" }, "dependencies": { + "@fastify/deepmerge": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.2.tgz", + "integrity": "sha512-3wuLdX5iiiYeZWP6bQrjqhrcvBIf0NHbQH1Ur1WbHvoiuTYUEItgygea3zs8aHpiitn0lOB8gX20u1qO+FDm7Q==" + }, "@opentelemetry/api-logs": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz", - "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.218.0.tgz", + "integrity": "sha512-fmEWp5kXlGEc3i/lR698Hz41DfGyN4Tbe4g7L1AxSc7fF8Xeh/FQ9Quqpa9dVA413Q1Ad43QOLzU4JoXgbFPWw==", "requires": { "@opentelemetry/api": "^1.3.0" } }, - "@opentelemetry/context-async-hooks": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.0.1.tgz", - "integrity": "sha512-XuY23lSI3d4PEqKA+7SLtAgwqIfc6E/E9eAQWLN1vlpC53ybO3o6jW4BsXo1xvz9lYyyWItfQDDLzezER01mCw==", - "requires": {} - }, - "@opentelemetry/core": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz", - "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==", + "@opentelemetry/configuration": { + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/configuration/-/configuration-0.218.0.tgz", + "integrity": "sha512-W8wIz7H2R1pufR5jfjb3gU2XkMpm2x/7b1RJcsuzvd70Il/rWWE+g5/Od7hQKrxRTSrTrOWlru101PWXz5I1EQ==", "requires": { - "@opentelemetry/semantic-conventions": "^1.29.0" + "@opentelemetry/core": "2.7.1", + "yaml": "^2.0.0" } }, + "@opentelemetry/context-async-hooks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.7.1.tgz", + "integrity": "sha512-OPFBYuXEn1E4ja3Y6eeA7O+ZnLBNcXTV5Cgsn1VaqBZ6hC5FnpZPLBNme1LJY8ZtF4aOujPKFoeWN4ik487KuQ==", + "requires": {} + }, "@opentelemetry/exporter-logs-otlp-grpc": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.203.0.tgz", - "integrity": "sha512-g/2Y2noc/l96zmM+g0LdeuyYKINyBwN6FJySoU15LHPLcMN/1a0wNk2SegwKcxrRdE7Xsm7fkIR5n6XFe3QpPw==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.218.0.tgz", + "integrity": "sha512-hoxrNH1l/Xy6F9WTJ5IK+6j1r9nQFlPOmrnTlhYHTySdunfXLmUCPv3bQtKYntxag9h3wLYBZQ2HI6FOx+BT2g==", "requires": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/sdk-logs": "0.203.0" + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/sdk-logs": "0.218.0" } }, "@opentelemetry/exporter-logs-otlp-http": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.203.0.tgz", - "integrity": "sha512-s0hys1ljqlMTbXx2XiplmMJg9wG570Z5lH7wMvrZX6lcODI56sG4HL03jklF63tBeyNwK2RV1/ntXGo3HgG4Qw==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.218.0.tgz", + "integrity": "sha512-Qx+4rpVHzgg89dawcWRHyt+XRXeLnhFz/qBtvggmjkcgPUdr+NAB0/u/eIPA8yAeJV0J80Vz43JZCh/XFvZFGw==", "requires": { - "@opentelemetry/api-logs": "0.203.0", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/sdk-logs": "0.203.0" + "@opentelemetry/api-logs": "0.218.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/sdk-logs": "0.218.0" } }, "@opentelemetry/exporter-logs-otlp-proto": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.203.0.tgz", - "integrity": "sha512-nl/7S91MXn5R1aIzoWtMKGvqxgJgepB/sH9qW0rZvZtabnsjbf8OQ1uSx3yogtvLr0GzwD596nQKz2fV7q2RBw==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.218.0.tgz", + "integrity": "sha512-1/noQNsp9gXD75HPzgjBrcF1+XTtry7pFAUfxVEJgg7mPv2AawKQuYkhMmJ8qjxz4Ubc3Y8bwvfxevXsKTq4cg==", "requires": { - "@opentelemetry/api-logs": "0.203.0", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-logs": "0.203.0", - "@opentelemetry/sdk-trace-base": "2.0.1" + "@opentelemetry/api-logs": "0.218.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.218.0", + "@opentelemetry/sdk-trace-base": "2.7.1" } }, "@opentelemetry/exporter-metrics-otlp-grpc": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.203.0.tgz", - "integrity": "sha512-FCCj9nVZpumPQSEI57jRAA89hQQgONuoC35Lt+rayWY/mzCAc6BQT7RFyFaZKJ2B7IQ8kYjOCPsF/HGFWjdQkQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.218.0.tgz", + "integrity": "sha512-YapQ9vNMX0NSZF6LK5pWAFfjpJleV2O9uYWfYGeb/5F1Kb9rPGK8tZDMJFa/sOksgdFuflDvYuA0B4qjDB4fjQ==", "requires": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-metrics": "2.0.1" + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.218.0", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1" } }, "@opentelemetry/exporter-metrics-otlp-http": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.203.0.tgz", - "integrity": "sha512-HFSW10y8lY6BTZecGNpV3GpoSy7eaO0Z6GATwZasnT4bEsILp8UJXNG5OmEsz4SdwCSYvyCbTJdNbZP3/8LGCQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.218.0.tgz", + "integrity": "sha512-bV7d2OuMpZu2+gAaxUAhzfZ0h3WVZk8ETQUEE3DNSntbTaMpuITjtm8I0rNyHFdm7Ax57K6ty7SgFXlBmOLIvQ==", "requires": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-metrics": "2.0.1" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1" } }, "@opentelemetry/exporter-metrics-otlp-proto": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.203.0.tgz", - "integrity": "sha512-OZnhyd9npU7QbyuHXFEPVm3LnjZYifuKpT3kTnF84mXeEQ84pJJZgyLBpU4FSkSwUkt/zbMyNAI7y5+jYTWGIg==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.218.0.tgz", + "integrity": "sha512-ubLddKjWULhla9YZRCj/rTBeppjJYE4e9w0icx5mTu3eFhWjQzbV75NYjXuIlEG+NJsBl6d+sTFw5Qu+oej4oQ==", "requires": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-metrics": "2.0.1" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.218.0", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1" } }, "@opentelemetry/exporter-prometheus": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.203.0.tgz", - "integrity": "sha512-2jLuNuw5m4sUj/SncDf/mFPabUxMZmmYetx5RKIMIQyPnl6G6ooFzfeE8aXNRf8YD1ZXNlCnRPcISxjveGJHNg==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.218.0.tgz", + "integrity": "sha512-RT5oEyu1kddZJ1vt7/BUo5wV+P7hpNAESsR3dUd3+8deHuX7gWNoCOZn+SfDT+hJHlIJ5h/AxiCLXIrutswDJg==", "requires": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-metrics": "2.0.1" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" } }, "@opentelemetry/exporter-trace-otlp-grpc": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.203.0.tgz", - "integrity": "sha512-322coOTf81bm6cAA8+ML6A+m4r2xTCdmAZzGNTboPXRzhwPt4JEmovsFAs+grpdarObd68msOJ9FfH3jxM6wqA==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.218.0.tgz", + "integrity": "sha512-3fXxVQEj9TNAFaCi79JeFKfeLd0sDtInaR3gaZDVlzNSPHtz8PZuCV34JKWjD4XXzT20IdMe8IpX6mRVNDA4Tw==", "requires": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-trace-base": "2.0.1" + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" } }, "@opentelemetry/exporter-trace-otlp-http": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.203.0.tgz", - "integrity": "sha512-ZDiaswNYo0yq/cy1bBLJFe691izEJ6IgNmkjm4C6kE9ub/OMQqDXORx2D2j8fzTBTxONyzusbaZlqtfmyqURPw==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.218.0.tgz", + "integrity": "sha512-8dqezsmPhtKitIK/eTipZhYl9EX2/gNQ5zUMhaz3uxEURwfkNf8IPvo6yNfrzbxdtpAOybS/+h7wmIWYqFSpiw==", "requires": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-trace-base": "2.0.1" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" } }, "@opentelemetry/exporter-trace-otlp-proto": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.203.0.tgz", - "integrity": "sha512-1xwNTJ86L0aJmWRwENCJlH4LULMG2sOXWIVw+Szta4fkqKVY50Eo4HoVKKq6U9QEytrWCr8+zjw0q/ZOeXpcAQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.218.0.tgz", + "integrity": "sha512-r1Msf8SNLRmwh9J6XQ5uh82D7CdDWMNHnPB7LAVHjzut0TkSeKc5KcIvr4SvHvfk/xwN5gxC+VLKQ1k0o8PSPw==", "requires": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-trace-base": "2.0.1" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" } }, "@opentelemetry/exporter-zipkin": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.0.1.tgz", - "integrity": "sha512-a9eeyHIipfdxzCfc2XPrE+/TI3wmrZUDFtG2RRXHSbZZULAny7SyybSvaDvS77a7iib5MPiAvluwVvbGTsHxsw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.7.1.tgz", + "integrity": "sha512-mfsD9bKAxcKrh5+y08TPodvClBO0CznBE3p79YAGnO81WI4LrdsGA65T53e4iTSbCalW4WaUpkbeJcbpyIUHfg==", "requires": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-trace-base": "2.0.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1", "@opentelemetry/semantic-conventions": "^1.29.0" } }, "@opentelemetry/instrumentation": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.203.0.tgz", - "integrity": "sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.218.0.tgz", + "integrity": "sha512-mIZil8Es+sYDK5m+DQiwAwF57F14TF2YlEqvIjZ/RQWcxDBwRGsKfdK2Tv65OU9meQKCMzSIFS9mxAcnAb6Bkg==", "requires": { - "@opentelemetry/api-logs": "0.203.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1" + "@opentelemetry/api-logs": "0.218.0", + "import-in-the-middle": "^3.0.0", + "require-in-the-middle": "^8.0.0" } }, "@opentelemetry/instrumentation-http": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.203.0.tgz", - "integrity": "sha512-y3uQAcCOAwnO6vEuNVocmpVzG3PER6/YZqbPbbffDdJ9te5NkHEkfSMNzlC3+v7KlE+WinPGc3N7MR30G1HY2g==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.218.0.tgz", + "integrity": "sha512-x9djaqdzpT8WAboep1H9nCAQ1E+MMsm08TNfA02TqM3bNNddZeiim+E3KMWVQFaX6JpUy7V0nm/wfN/K2Em+Zw==", "requires": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/instrumentation": "0.203.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/instrumentation": "0.218.0", "@opentelemetry/semantic-conventions": "^1.29.0", "forwarded-parse": "2.1.2" } }, "@opentelemetry/instrumentation-undici": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.14.0.tgz", - "integrity": "sha512-2HN+7ztxAReXuxzrtA3WboAKlfP5OsPA57KQn2AdYZbJ3zeRPcLXyW4uO/jpLE6PLm0QRtmeGCmfYpqRlwgSwg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.28.0.tgz", + "integrity": "sha512-7nh4Gw7PhYtQm82FIJtWUhx6iZQJj0bdkKe2RQb3XNIyxu0o9rM1J5Xt083SsG2tCbQZpX9/mlDxhTrK1Z/lVQ==", "requires": { "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.203.0" + "@opentelemetry/instrumentation": "^0.218.0", + "@opentelemetry/semantic-conventions": "^1.24.0" } }, "@opentelemetry/otlp-exporter-base": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.203.0.tgz", - "integrity": "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==", - "requires": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-transformer": "0.203.0" + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.218.0.tgz", + "integrity": "sha512-ZwqpkNL5W7RyGJPDZ9g06DvKp8KFTWPJPN12anpMQYSKpTSU0z3EIZuPq9vPGpS8siFyOqDYDAuCwlNO9FqgbA==", + "requires": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-transformer": "0.218.0" } }, "@opentelemetry/otlp-grpc-exporter-base": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.203.0.tgz", - "integrity": "sha512-te0Ze1ueJF+N/UOFl5jElJW4U0pZXQ8QklgSfJ2linHN0JJsuaHG8IabEUi2iqxY8ZBDlSiz1Trfv5JcjWWWwQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.218.0.tgz", + "integrity": "sha512-H/lCGJ536N98VpYJOaWTQOkv4Dx6TnmStK6Rqfu1W7KkFbPAx04hjdYEMZF/YbnHzPUSIK4kM6OE2GKGBTpV9A==", "requires": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/otlp-exporter-base": "0.203.0", - "@opentelemetry/otlp-transformer": "0.203.0" + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/otlp-transformer": "0.218.0" } }, "@opentelemetry/otlp-transformer": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.203.0.tgz", - "integrity": "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.218.0.tgz", + "integrity": "sha512-CFaKH87WAzjuJ4awowTTLzUvMfaRfiOFG5+qm5S5ncyalRtN4ecQ+YmuANJSCrVPuvZFEkUgKhBPBndxi3rHsQ==", "requires": { - "@opentelemetry/api-logs": "0.203.0", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-logs": "0.203.0", - "@opentelemetry/sdk-metrics": "2.0.1", - "@opentelemetry/sdk-trace-base": "2.0.1", - "protobufjs": "^7.3.0" + "@opentelemetry/api-logs": "0.218.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.218.0", + "@opentelemetry/sdk-metrics": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" } }, "@opentelemetry/propagator-b3": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-2.0.1.tgz", - "integrity": "sha512-Hc09CaQ8Tf5AGLmf449H726uRoBNGPBL4bjr7AnnUpzWMvhdn61F78z9qb6IqB737TffBsokGAK1XykFEZ1igw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-2.7.1.tgz", + "integrity": "sha512-RJid6E2CKyeGfKBzXKF21ejabGMHypFkPAh3qZ+NvI+SGjuIye79t3PmiqcDgtRzdKH6ynXzbfslQ8DfpRUg2A==", "requires": { - "@opentelemetry/core": "2.0.1" + "@opentelemetry/core": "2.7.1" } }, "@opentelemetry/propagator-jaeger": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.0.1.tgz", - "integrity": "sha512-7PMdPBmGVH2eQNb/AtSJizQNgeNTfh6jQFqys6lfhd6P4r+m/nTh3gKPPpaCXVdRQ+z93vfKk+4UGty390283w==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.7.1.tgz", + "integrity": "sha512-KMjVBHzP4N60bOzxja76M1F1hZZ43lGPga5ix+mkv9+kk1nx9SbkxSvJsMbuVUxdPQmsPTqGShmhN8ulrMOg6Q==", "requires": { - "@opentelemetry/core": "2.0.1" + "@opentelemetry/core": "2.7.1" } }, "@opentelemetry/resources": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz", - "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.7.1.tgz", + "integrity": "sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==", "requires": { - "@opentelemetry/core": "2.0.1", + "@opentelemetry/core": "2.7.1", "@opentelemetry/semantic-conventions": "^1.29.0" } }, "@opentelemetry/sdk-logs": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz", - "integrity": "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.218.0.tgz", + "integrity": "sha512-QvnNdugatFTVCJXH0Mcu7GOOJSylA9j127kIezOE4YwTI4YbowRons2K4WZTv5FMS8T4q9P0NdaRHdkSmeAIag==", "requires": { - "@opentelemetry/api-logs": "0.203.0", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/resources": "2.0.1" + "@opentelemetry/api-logs": "0.218.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" } }, "@opentelemetry/sdk-metrics": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz", - "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.7.1.tgz", + "integrity": "sha512-MpDJdkiFDs3Pm1RHO3KByuZbuBdJEXEAkiC0+yJdsZGVCdf1RpHR6n+LHDcS7ffmfrt5kVCzJSCfm4z2C7v0uQ==", "requires": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/resources": "2.0.1" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1" } }, "@opentelemetry/sdk-node": { - "version": "0.203.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.203.0.tgz", - "integrity": "sha512-zRMvrZGhGVMvAbbjiNQW3eKzW/073dlrSiAKPVWmkoQzah9wfynpVPeL55f9fVIm0GaBxTLcPeukWGy0/Wj7KQ==", + "version": "0.218.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.218.0.tgz", + "integrity": "sha512-tPMjHrLV5gsfNdYqoRHjeGbCAZBXXD9c1Qo/2ut7VwnUABDNh76xNxrT0SEhkIIJuCN45bbN1vZnYL1gY0IkOg==", "requires": { - "@opentelemetry/api-logs": "0.203.0", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/exporter-logs-otlp-grpc": "0.203.0", - "@opentelemetry/exporter-logs-otlp-http": "0.203.0", - "@opentelemetry/exporter-logs-otlp-proto": "0.203.0", - "@opentelemetry/exporter-metrics-otlp-grpc": "0.203.0", - "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", - "@opentelemetry/exporter-metrics-otlp-proto": "0.203.0", - "@opentelemetry/exporter-prometheus": "0.203.0", - "@opentelemetry/exporter-trace-otlp-grpc": "0.203.0", - "@opentelemetry/exporter-trace-otlp-http": "0.203.0", - "@opentelemetry/exporter-trace-otlp-proto": "0.203.0", - "@opentelemetry/exporter-zipkin": "2.0.1", - "@opentelemetry/instrumentation": "0.203.0", - "@opentelemetry/propagator-b3": "2.0.1", - "@opentelemetry/propagator-jaeger": "2.0.1", - "@opentelemetry/resources": "2.0.1", - "@opentelemetry/sdk-logs": "0.203.0", - "@opentelemetry/sdk-metrics": "2.0.1", - "@opentelemetry/sdk-trace-base": "2.0.1", - "@opentelemetry/sdk-trace-node": "2.0.1", + "@opentelemetry/api-logs": "0.218.0", + "@opentelemetry/configuration": "0.218.0", + "@opentelemetry/context-async-hooks": "2.7.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/exporter-logs-otlp-grpc": "0.218.0", + "@opentelemetry/exporter-logs-otlp-http": "0.218.0", + "@opentelemetry/exporter-logs-otlp-proto": "0.218.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "0.218.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.218.0", + "@opentelemetry/exporter-metrics-otlp-proto": "0.218.0", + "@opentelemetry/exporter-prometheus": "0.218.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.218.0", + "@opentelemetry/exporter-trace-otlp-http": "0.218.0", + "@opentelemetry/exporter-trace-otlp-proto": "0.218.0", + "@opentelemetry/exporter-zipkin": "2.7.1", + "@opentelemetry/instrumentation": "0.218.0", + "@opentelemetry/otlp-exporter-base": "0.218.0", + "@opentelemetry/propagator-b3": "2.7.1", + "@opentelemetry/propagator-jaeger": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.218.0", + "@opentelemetry/sdk-metrics": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1", + "@opentelemetry/sdk-trace-node": "2.7.1", "@opentelemetry/semantic-conventions": "^1.29.0" } }, "@opentelemetry/sdk-trace-base": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz", - "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", "requires": { - "@opentelemetry/core": "2.0.1", - "@opentelemetry/resources": "2.0.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", "@opentelemetry/semantic-conventions": "^1.29.0" } }, "@opentelemetry/sdk-trace-node": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.0.1.tgz", - "integrity": "sha512-UhdbPF19pMpBtCWYP5lHbTogLWx9N0EBxtdagvkn5YtsAnCBZzL7SjktG+ZmupRgifsHMjwUaCCaVmqGfSADmA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.7.1.tgz", + "integrity": "sha512-pCpQxU68lV+I9s9svqMyVu5iHdDDUnqUpSxqwyCU8A9ejEsSnMPCbearwsUO4yk08ZJzAIUCFuReMdVQvHrdvg==", "requires": { - "@opentelemetry/context-async-hooks": "2.0.1", - "@opentelemetry/core": "2.0.1", - "@opentelemetry/sdk-trace-base": "2.0.1" + "@opentelemetry/context-async-hooks": "2.7.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" } }, - "@opentelemetry/semantic-conventions": { - "version": "1.36.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.36.0.tgz", - "integrity": "sha512-TtxJSRD8Ohxp6bKkhrm27JRHAxPczQA7idtcTOMYI+wQRRrfgqxHv1cFbCApcSnNjtXkmzFozn6jQtFrOmbjPQ==" - }, - "debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "requires": { - "ms": "^2.1.3" + "@platformatic/foundation": { + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/foundation/-/foundation-3.56.0.tgz", + "integrity": "sha512-q0w1DNUS9YUWELXoYDwcicBOxmbqPT9T4zmKHNjEdRPSaD2vf9k50GvSyB8LDFhVxjWekJug6IkPl6P9kaG+wQ==", + "requires": { + "@fastify/deepmerge": "^2.0.0", + "@fastify/error": "^4.0.0", + "@iarna/toml": "^2.2.5", + "@watchable/unpromise": "^1.0.2", + "ajv": "^8.12.0", + "boring-name-generator": "^1.0.3", + "colorette": "^2.0.19", + "debug": "^4.4.3", + "fast-json-patch": "^3.1.1", + "json5": "^2.2.3", + "leven": "~3.1.0", + "pino": "^9.9.0", + "pino-pretty": "^13.0.0", + "semver": "^7.6.3", + "undici": "7.24.0", + "yaml": "^2.4.1" } }, + "cjs-module-lexer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==" + }, "import-in-the-middle": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", - "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-3.0.2.tgz", + "integrity": "sha512-LGLYRl0A2gtyUJb2WDliBHmk6TtlHwdDjxonacZ8QrEs/ZW+YDgNv2QAfjRQWpS8HqvNcq6GGnN6jrOa5FysDQ==", "requires": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", - "cjs-module-lexer": "^1.2.2", - "module-details-from-path": "^1.0.3" + "cjs-module-lexer": "^2.2.0", + "module-details-from-path": "^1.0.4" + } + }, + "pino": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", + "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==", + "requires": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" } }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "requires": { + "split2": "^4.0.0" + } }, - "require-in-the-middle": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", - "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", + "thread-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz", + "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==", "requires": { - "debug": "^4.3.5", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.8" + "real-require": "^0.2.0" } + }, + "undici": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.0.tgz", + "integrity": "sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==" } } }, @@ -24263,13 +25795,21 @@ "integrity": "sha512-/JVfPhyUW0GQkmr5lGAGOgh0lpJbTcLG8VB2uNqgNgH1fhPPFAM0l4pLSyeDzpTj2r/GJPLqhzvCgangnSHfoQ==" }, "@platformatic/wattpm-pprof-capture": { - "version": "3.52.1", - "resolved": "https://registry.npmjs.org/@platformatic/wattpm-pprof-capture/-/wattpm-pprof-capture-3.52.1.tgz", - "integrity": "sha512-OHcHxSKmDba6RURkN4vwAoCE2H5zJULhhlntKOiJo5MdUK4Z5j8gVXvj/Zee5Nr4QWwYyNq4kwgoGCLLPC5tcw==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/@platformatic/wattpm-pprof-capture/-/wattpm-pprof-capture-3.56.0.tgz", + "integrity": "sha512-HHBdd3BkHIIUXVSI587GV7/KvKzKvdn7twoqitIEKHtHgvQIQtPV9MPTir2FMMV4CVThuTSMoY6TXTWPlbLspA==", "requires": { "@datadog/pprof": "^5.3.0", "@fastify/error": "^4.0.0", - "undici": "^7.0.0" + "@platformatic/globals": "3.56.0", + "undici": "^7.27.2" + }, + "dependencies": { + "undici": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==" + } } }, "@protobufjs/aspromise": { @@ -26539,11 +28079,11 @@ "integrity": "sha512-Xks6RUDLZFdz8LIdR6q0MTH44k7FikOmnh5xkSjMig6ch45afc8sjTjRQf3P6ax8dMgcQrYO/AR2RGWURrruqw==" }, "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "delayed-stream": { @@ -26725,6 +28265,37 @@ "bare-events": "^2.7.0" } }, + "execa": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", + "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", + "requires": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.6", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.2.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.1.1" + }, + "dependencies": { + "is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==" + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" + } + } + }, "expect-type": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", @@ -27016,6 +28587,22 @@ "es-object-atoms": "^1.0.0" } }, + "get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "requires": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "dependencies": { + "is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==" + } + } + }, "get-tsconfig": { "version": "4.7.5", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", @@ -27157,6 +28744,11 @@ "debug": "4" } }, + "human-signals": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==" + }, "humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -27717,9 +29309,9 @@ "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==" }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "multistream": { "version": "4.1.0", @@ -27759,6 +29351,22 @@ "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.9.0.tgz", "integrity": "sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A==" }, + "npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "requires": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "dependencies": { + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==" + } + } + }, "oauth4webapi": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.1.tgz", @@ -27817,144 +29425,169 @@ } }, "otlp-logger": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/otlp-logger/-/otlp-logger-1.1.13.tgz", - "integrity": "sha512-r53tPnMLprtQSMOJUkj4Az4tR8NL+U+8C7M8BV1ZA9y7cDfAbWQp2mRL/eYS/O786oAi9KnN9hKsZ5cFKNchKw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/otlp-logger/-/otlp-logger-2.1.0.tgz", + "integrity": "sha512-UlhiSefpUsuP6hRWpX9UMje71ehvtAhrgXPUUiiqQ1miSwbjLCG+f1TN/mz7dWiOuhwl+VDKi9j+S8DJYAv5bA==", + "dev": true, "requires": { - "@opentelemetry/api-logs": "^0.206.0", - "@opentelemetry/exporter-logs-otlp-grpc": "^0.206.0", - "@opentelemetry/exporter-logs-otlp-http": "^0.206.0", - "@opentelemetry/exporter-logs-otlp-proto": "^0.206.0", + "@opentelemetry/api-logs": "^0.217.0", + "@opentelemetry/exporter-logs-otlp-grpc": "^0.217.0", + "@opentelemetry/exporter-logs-otlp-http": "^0.217.0", + "@opentelemetry/exporter-logs-otlp-proto": "^0.217.0", "@opentelemetry/resources": "^2.0.0", - "@opentelemetry/sdk-logs": "^0.206.0" + "@opentelemetry/sdk-logs": "^0.217.0" }, "dependencies": { "@opentelemetry/api-logs": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.206.0.tgz", - "integrity": "sha512-yIVDu9jX//nV5wSMLZLdHdb1SKHIMj9k+wQVFtln5Flcgdldz9BkHtavvExQiJqBZg2OpEEJEZmzQazYztdz2A==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.217.0.tgz", + "integrity": "sha512-Cdq0jW2lknrNfrAm92MyEAvpe2cRsKjdnQLHUL6xRA4IVUnsWx6P65E7NcUO0Y+L4w1Aee5iV8FvjSwd+lrs9A==", + "dev": true, "requires": { "@opentelemetry/api": "^1.3.0" } }, - "@opentelemetry/core": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.1.0.tgz", - "integrity": "sha512-RMEtHsxJs/GiHHxYT58IY57UXAQTuUnZVco6ymDEqTNlJKTimM4qPUPVe8InNFyBjhHBEAx4k3Q8LtNayBsbUQ==", - "requires": { - "@opentelemetry/semantic-conventions": "^1.29.0" - } - }, "@opentelemetry/exporter-logs-otlp-grpc": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.206.0.tgz", - "integrity": "sha512-kJKxKBaGwqWop95d6tcluz260IWwIgOG0BH8oVm6429tg8LxY2PJb7Om8d5s+5vOFM8DkUYCnIpn9d/13/RcKQ==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.217.0.tgz", + "integrity": "sha512-vC5S0Dc+noxD86CVtNu1+awCHPA5Kewi1Sg23ps+9lh4YifwsKXh3pe4XTNEKtUJiAcjpJ5dqStGakLbrSE+YQ==", + "dev": true, "requires": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "2.1.0", - "@opentelemetry/otlp-exporter-base": "0.206.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.206.0", - "@opentelemetry/otlp-transformer": "0.206.0", - "@opentelemetry/sdk-logs": "0.206.0" + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/sdk-logs": "0.217.0" } }, "@opentelemetry/exporter-logs-otlp-http": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.206.0.tgz", - "integrity": "sha512-VWcHEnS+1kN+sQTAdCgSn2anqHPxY1/e52fhpe2mcSnEaXI1srFf3RU5DAu7hzQO6T9DPQzOKG8kc76vCtyYDw==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.217.0.tgz", + "integrity": "sha512-KfLAdt1uilVE+3FxbgVnp2ZrzqbIawzcesnRoi+Kh9ckB5Ld5D8btUgoBvwTbdmuNx1j6b132Wsh72azq+pPNQ==", + "dev": true, "requires": { - "@opentelemetry/api-logs": "0.206.0", - "@opentelemetry/core": "2.1.0", - "@opentelemetry/otlp-exporter-base": "0.206.0", - "@opentelemetry/otlp-transformer": "0.206.0", - "@opentelemetry/sdk-logs": "0.206.0" + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/sdk-logs": "0.217.0" } }, "@opentelemetry/exporter-logs-otlp-proto": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.206.0.tgz", - "integrity": "sha512-CsYNXJwkn1qCXJGE+/JvvYucAjL8rpaxa2hnl+tDP6M5E0O3UVa8zG4ZUEebjr5J5Nc32egvslEZx5rgNOp3lQ==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.217.0.tgz", + "integrity": "sha512-Se0GG/ZO24mQTlQj7zprR4pNI0nKe4lPDPBsuJmi6508b9TlZEuUd3EfyuHk6oJxzL7fGyDFYAbxNigQvRP2ZQ==", + "dev": true, "requires": { - "@opentelemetry/api-logs": "0.206.0", - "@opentelemetry/core": "2.1.0", - "@opentelemetry/otlp-exporter-base": "0.206.0", - "@opentelemetry/otlp-transformer": "0.206.0", - "@opentelemetry/resources": "2.1.0", - "@opentelemetry/sdk-logs": "0.206.0", - "@opentelemetry/sdk-trace-base": "2.1.0" + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.217.0", + "@opentelemetry/sdk-trace-base": "2.7.1" } }, "@opentelemetry/otlp-exporter-base": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.206.0.tgz", - "integrity": "sha512-Rv54oSNKMHYS5hv+H5EGksfBUtvPQWFTK+Dk6MjJun9tOijCsFJrhRFvAqg5d67TWSMn+ZQYRKIeXh5oLVrpAQ==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.217.0.tgz", + "integrity": "sha512-eYfqnB3UhKu/5frhd1R6+FprKygbhkomuaceMXDyzxbfXB9tKgZOVmjaJ02CkLA6Tdzumxl+e2H+vo2a8jiMPQ==", + "dev": true, "requires": { - "@opentelemetry/core": "2.1.0", - "@opentelemetry/otlp-transformer": "0.206.0" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-transformer": "0.217.0" } }, "@opentelemetry/otlp-grpc-exporter-base": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.206.0.tgz", - "integrity": "sha512-IA8EDbrB8OKtidMqErBY8sUc9mh03LOXuNPwp4/rdPrxSt45g1gBuZMovRXdEWfRyKKbF2E7MdipT2m11bs6SQ==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.217.0.tgz", + "integrity": "sha512-7RTAdZuOsCDnsyqTCG4+bDzrfnsWdzkRs7z0AVi/V3tEQx0oKeyc+OuRWYxnRsmaJXgxcmB8vb/lfxn58Dj6Ag==", + "dev": true, "requires": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "2.1.0", - "@opentelemetry/otlp-exporter-base": "0.206.0", - "@opentelemetry/otlp-transformer": "0.206.0" + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0" } }, "@opentelemetry/otlp-transformer": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.206.0.tgz", - "integrity": "sha512-Li2Cik1WnmNbU2mmTnw7DxvRiXhMcnAuTfAclP8y/zy7h5+GrLDpTZ+Z0XUs+Q3MLkb/h3ry4uFrC/z+2a6X7g==", - "requires": { - "@opentelemetry/api-logs": "0.206.0", - "@opentelemetry/core": "2.1.0", - "@opentelemetry/resources": "2.1.0", - "@opentelemetry/sdk-logs": "0.206.0", - "@opentelemetry/sdk-metrics": "2.1.0", - "@opentelemetry/sdk-trace-base": "2.1.0", - "protobufjs": "^7.3.0" + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.217.0.tgz", + "integrity": "sha512-MKK8UHKFUOGAvbZRWh90MhwHG+Fxm6OROBdjKPCF+HQobjuJ/Kuf8Chs8CR45X1aqotxrMj7OxTdsXe8sXuGVA==", + "dev": true, + "requires": { + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.217.0", + "@opentelemetry/sdk-metrics": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1", + "protobufjs": "8.0.1" } }, "@opentelemetry/resources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.1.0.tgz", - "integrity": "sha512-1CJjf3LCvoefUOgegxi8h6r4B/wLSzInyhGP2UmIBYNlo4Qk5CZ73e1eEyWmfXvFtm1ybkmfb2DqWvspsYLrWw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.7.1.tgz", + "integrity": "sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==", + "dev": true, "requires": { - "@opentelemetry/core": "2.1.0", + "@opentelemetry/core": "2.7.1", "@opentelemetry/semantic-conventions": "^1.29.0" } }, "@opentelemetry/sdk-logs": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.206.0.tgz", - "integrity": "sha512-SQ2yTmqe4Mw9RI3a/glVkfjWPsXh6LySvnljXubiZq4zu+UP8NMJt2j82ZsYb+KpD7Eu+/41/7qlJnjdeVjz7Q==", + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.217.0.tgz", + "integrity": "sha512-BB+PcHItcZDL63dPMW+mJvwN9rk37wuIDjRxbVlg6pPDvDR/7GL7UJHbGsllgoggOoTimsKgENaWPoGch/oE1A==", + "dev": true, "requires": { - "@opentelemetry/api-logs": "0.206.0", - "@opentelemetry/core": "2.1.0", - "@opentelemetry/resources": "2.1.0" + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" } }, "@opentelemetry/sdk-metrics": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.1.0.tgz", - "integrity": "sha512-J9QX459mzqHLL9Y6FZ4wQPRZG4TOpMCyPOh6mkr/humxE1W2S3Bvf4i75yiMW9uyed2Kf5rxmLhTm/UK8vNkAw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.7.1.tgz", + "integrity": "sha512-MpDJdkiFDs3Pm1RHO3KByuZbuBdJEXEAkiC0+yJdsZGVCdf1RpHR6n+LHDcS7ffmfrt5kVCzJSCfm4z2C7v0uQ==", + "dev": true, "requires": { - "@opentelemetry/core": "2.1.0", - "@opentelemetry/resources": "2.1.0" + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1" } }, "@opentelemetry/sdk-trace-base": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.1.0.tgz", - "integrity": "sha512-uTX9FBlVQm4S2gVQO1sb5qyBLq/FPjbp+tmGoxu4tIgtYGmBYB44+KX/725RFDe30yBSaA9Ml9fqphe1hbUyLQ==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "dev": true, "requires": { - "@opentelemetry/core": "2.1.0", - "@opentelemetry/resources": "2.1.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", "@opentelemetry/semantic-conventions": "^1.29.0" } + }, + "protobufjs": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.0.1.tgz", + "integrity": "sha512-NWWCCscLjs+cOKF/s/XVNFRW7Yih0fdH+9brffR5NZCy8k42yRdl5KlWKMVXuI1vfCoy4o1z80XR/W/QUb3V3w==", + "dev": true, + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + } } } }, @@ -28169,11 +29802,12 @@ } }, "pino-opentelemetry-transport": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pino-opentelemetry-transport/-/pino-opentelemetry-transport-2.0.0.tgz", - "integrity": "sha512-tWoq02WEtnCWfr63Co1n0sGlDpkBz2YUovSAsSBv/+jwKUIn/PjxwRileGViKrH/K3e+oc71nGl6yUdgQlrVkg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pino-opentelemetry-transport/-/pino-opentelemetry-transport-3.0.0.tgz", + "integrity": "sha512-t/fH23X+/pSSaUTdD7hq8FbT5BtTnUvXDojxKNVGX/auDPpDshG58t2yxFr2cmMgpQetIKBCcsH3KmcJXJJ5cQ==", + "dev": true, "requires": { - "otlp-logger": "^1.1.4", + "otlp-logger": "^2.0.0", "pino-abstract-transport": "^3.0.0" }, "dependencies": { @@ -28181,6 +29815,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", + "dev": true, "requires": { "split2": "^4.0.0" } @@ -28475,21 +30110,6 @@ "requires": { "debug": "^4.3.5", "module-details-from-path": "^1.0.3" - }, - "dependencies": { - "debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "requires": { - "ms": "^2.1.3" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } } }, "requires-port": { @@ -28815,607 +30435,1313 @@ "text-decoder": "^1.1.0" } }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-final-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==" + }, + "strnum": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.3.tgz", + "integrity": "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "swap-case": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-3.0.3.tgz", + "integrity": "sha512-6p4op8wE9CQv7uDFzulI6YXUw4lD9n4oQierdbFThEKVWVQcbQcUjdP27W8XE7V4QnWmnq9jueSHceyyQnqQVA==" + }, + "systeminformation": { + "version": "5.31.2", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.2.tgz", + "integrity": "sha512-ietGQGFhhZNBPgNv9vljgT8gzbYgQr6t0yGAo0Vdb5Jyilb574Vp+AuX2Or9rpBq3ho4mJRawLIUa9+CiILJdg==" + }, + "table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "requires": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + } + }, + "tar-fs": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", + "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", + "requires": { + "bare-fs": "^4.0.1", + "bare-path": "^3.0.0", + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + } + }, + "tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "requires": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "tdigest": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", + "integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==", + "requires": { + "bintrees": "1.0.2" + } + }, + "text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "requires": { + "b4a": "^1.6.4" + } + }, + "thread-stream": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.0.0.tgz", + "integrity": "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==", + "requires": { + "real-require": "^0.2.0" + } + }, + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + }, + "tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true + }, + "tinyexec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", + "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", + "dev": true + }, + "tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "requires": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "dependencies": { + "fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "requires": {} + }, + "picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true + } + } + }, + "tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "dev": true + }, + "title-case": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/title-case/-/title-case-3.0.3.tgz", + "integrity": "sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==", "requires": { - "safe-buffer": "~5.2.0" + "tslib": "^2.0.3" } }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "is-number": "^7.0.0" } }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "toad-cache": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz", + "integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==" + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "ts-algebra": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.2.2.tgz", + "integrity": "sha512-kloPhf1hq3JbCPOTYoOWDKxebWjNb2o/LKnNfkWhxVVisFFmMJPPdJeGoGmM+iRLyoXAR61e08Pb+vUXINg8aA==", + "dev": true + }, + "tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, "requires": { - "ansi-regex": "^5.0.1" + "esbuild": "~0.27.0", + "fsevents": "~2.3.3", + "get-tsconfig": "^4.7.5" + }, + "dependencies": { + "@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "dev": true, + "optional": true + }, + "@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "dev": true, + "optional": true + }, + "esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "dev": true, + "requires": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + } } }, - "strnum": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.3.tgz", - "integrity": "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "tus-js-client": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-4.3.1.tgz", + "integrity": "sha512-ZLeYmjrkaU1fUsKbIi8JML52uAocjEZtBx4DKjRrqzrZa0O4MYwT6db+oqePlspV+FxXJAyFBc/L5gwUi2OFsg==", "dev": true, "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" - }, - "swap-case": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-3.0.3.tgz", - "integrity": "sha512-6p4op8wE9CQv7uDFzulI6YXUw4lD9n4oQierdbFThEKVWVQcbQcUjdP27W8XE7V4QnWmnq9jueSHceyyQnqQVA==" - }, - "systeminformation": { - "version": "5.31.2", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.2.tgz", - "integrity": "sha512-ietGQGFhhZNBPgNv9vljgT8gzbYgQr6t0yGAo0Vdb5Jyilb574Vp+AuX2Or9rpBq3ho4mJRawLIUa9+CiILJdg==" - }, - "table": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", - "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", - "requires": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - } - }, - "tar-fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", - "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", - "requires": { - "bare-fs": "^4.0.1", - "bare-path": "^3.0.0", - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - } - }, - "tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "requires": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, - "tdigest": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", - "integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==", - "requires": { - "bintrees": "1.0.2" - } - }, - "text-decoder": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", - "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", - "requires": { - "b4a": "^1.6.4" + "buffer-from": "^1.1.2", + "combine-errors": "^3.0.3", + "is-stream": "^2.0.0", + "js-base64": "^3.7.2", + "lodash.throttle": "^4.1.1", + "proper-lockfile": "^4.1.2", + "url-parse": "^1.5.7" } }, - "thread-stream": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.0.0.tgz", - "integrity": "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==", - "requires": { - "real-require": "^0.2.0" - } + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" }, - "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } + "typed-emitter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-0.1.0.tgz", + "integrity": "sha512-Tfay0l6gJMP5rkil8CzGbLthukn+9BN/VXWcABVFPjOoelJ+koW8BuPZYk+h/L+lEeIp1fSzVRiWRPIjKVjPdg==" }, - "tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true }, - "tinyexec": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", - "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", - "dev": true + "undici": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.6.tgz", + "integrity": "sha512-Xi4agocCbRzt0yYMZGMA6ApD7gvtUFaxm4ZmeacWI4cZxaF6C+8I8QfofC20NAePiB/IcvZmzkJ7XPa471AEtA==" }, - "tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", - "dev": true, + "undici-thread-interceptor": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/undici-thread-interceptor/-/undici-thread-interceptor-1.3.1.tgz", + "integrity": "sha512-s/TUkGeVj+C4Rr3Vsy84Kewj97m2QBNx6IjMGM1nzfoKWqNlcLqtFQCbXQjobRJQKi3u9Hc796/YvJIv7W7qWQ==", "requires": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "dependencies": { - "fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "requires": {} - }, - "picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true - } + "fastq": "^1.19.1", + "hyperid": "^3.2.0", + "light-my-request": "^6.5.1", + "undici": "^7.0.0" } }, - "tinyrainbow": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", - "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", - "dev": true + "undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==" }, - "title-case": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/title-case/-/title-case-3.0.3.tgz", - "integrity": "sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==", - "requires": { - "tslib": "^2.0.3" - } + "unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==" }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, "requires": { - "is-number": "^7.0.0" + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" } }, - "toad-cache": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz", - "integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==" - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "ts-algebra": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.2.2.tgz", - "integrity": "sha512-kloPhf1hq3JbCPOTYoOWDKxebWjNb2o/LKnNfkWhxVVisFFmMJPPdJeGoGmM+iRLyoXAR61e08Pb+vUXINg8aA==", - "dev": true + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, - "tsx": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", - "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "uuid-parse": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/uuid-parse/-/uuid-parse-1.1.0.tgz", + "integrity": "sha512-OdmXxA8rDsQ7YpNVbKSJkNzTw2I+S5WsbMDnCtIWSQaosNAcWtFuI/YK1TjzUI6nbkgiqEyh8gWngfcv8Asd9A==" + }, + "vitest": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.5.tgz", + "integrity": "sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==", "dev": true, "requires": { - "esbuild": "~0.27.0", - "fsevents": "~2.3.3", - "get-tsconfig": "^4.7.5" + "@vitest/expect": "4.1.5", + "@vitest/mocker": "4.1.5", + "@vitest/pretty-format": "4.1.5", + "@vitest/runner": "4.1.5", + "@vitest/snapshot": "4.1.5", + "@vitest/spy": "4.1.5", + "@vitest/utils": "4.1.5", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" }, "dependencies": { - "@esbuild/aix-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", - "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "@vitest/mocker": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.5.tgz", + "integrity": "sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==", "dev": true, - "optional": true + "requires": { + "@vitest/spy": "4.1.5", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + } }, - "@esbuild/android-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", - "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", - "dev": true, - "optional": true + "picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true }, - "@esbuild/android-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", - "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "vite": { + "version": "8.0.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.10.tgz", + "integrity": "sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==", "dev": true, - "optional": true + "requires": { + "fsevents": "~2.3.3", + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.10", + "rolldown": "1.0.0-rc.17", + "tinyglobby": "^0.2.16" + } + } + } + }, + "wattpm": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/wattpm/-/wattpm-3.52.0.tgz", + "integrity": "sha512-Lm8wkRLxjWkfKEXaAt2B6R5jeZ1GIt4UKCDL9sx+zS+lVd5r600kOvZ93sTFGzGetaD/ENXJtY35r6/YccEWIw==", + "requires": { + "@fastify/websocket": "^11.0.0", + "@platformatic/control": "3.52.0", + "@platformatic/foundation": "3.52.0", + "@platformatic/runtime": "3.52.0", + "colorette": "^2.0.20", + "pino-pretty": "^13.0.0", + "split2": "^4.2.0", + "table": "^6.8.2" + }, + "dependencies": { + "@opentelemetry/api-logs": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz", + "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==", + "requires": { + "@opentelemetry/api": "^1.3.0" + } }, - "@esbuild/android-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", - "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", - "dev": true, - "optional": true + "@opentelemetry/context-async-hooks": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.0.1.tgz", + "integrity": "sha512-XuY23lSI3d4PEqKA+7SLtAgwqIfc6E/E9eAQWLN1vlpC53ybO3o6jW4BsXo1xvz9lYyyWItfQDDLzezER01mCw==", + "requires": {} }, - "@esbuild/darwin-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", - "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", - "dev": true, - "optional": true + "@opentelemetry/core": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz", + "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==", + "requires": { + "@opentelemetry/semantic-conventions": "^1.29.0" + } }, - "@esbuild/darwin-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", - "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", - "dev": true, - "optional": true + "@opentelemetry/exporter-logs-otlp-grpc": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.203.0.tgz", + "integrity": "sha512-g/2Y2noc/l96zmM+g0LdeuyYKINyBwN6FJySoU15LHPLcMN/1a0wNk2SegwKcxrRdE7Xsm7fkIR5n6XFe3QpPw==", + "requires": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/sdk-logs": "0.203.0" + } }, - "@esbuild/freebsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", - "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", - "dev": true, - "optional": true + "@opentelemetry/exporter-logs-otlp-http": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.203.0.tgz", + "integrity": "sha512-s0hys1ljqlMTbXx2XiplmMJg9wG570Z5lH7wMvrZX6lcODI56sG4HL03jklF63tBeyNwK2RV1/ntXGo3HgG4Qw==", + "requires": { + "@opentelemetry/api-logs": "0.203.0", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/sdk-logs": "0.203.0" + } + }, + "@opentelemetry/exporter-logs-otlp-proto": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.203.0.tgz", + "integrity": "sha512-nl/7S91MXn5R1aIzoWtMKGvqxgJgepB/sH9qW0rZvZtabnsjbf8OQ1uSx3yogtvLr0GzwD596nQKz2fV7q2RBw==", + "requires": { + "@opentelemetry/api-logs": "0.203.0", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-logs": "0.203.0", + "@opentelemetry/sdk-trace-base": "2.0.1" + } + }, + "@opentelemetry/exporter-metrics-otlp-grpc": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.203.0.tgz", + "integrity": "sha512-FCCj9nVZpumPQSEI57jRAA89hQQgONuoC35Lt+rayWY/mzCAc6BQT7RFyFaZKJ2B7IQ8kYjOCPsF/HGFWjdQkQ==", + "requires": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-metrics": "2.0.1" + } + }, + "@opentelemetry/exporter-metrics-otlp-http": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.203.0.tgz", + "integrity": "sha512-HFSW10y8lY6BTZecGNpV3GpoSy7eaO0Z6GATwZasnT4bEsILp8UJXNG5OmEsz4SdwCSYvyCbTJdNbZP3/8LGCQ==", + "requires": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-metrics": "2.0.1" + } + }, + "@opentelemetry/exporter-metrics-otlp-proto": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.203.0.tgz", + "integrity": "sha512-OZnhyd9npU7QbyuHXFEPVm3LnjZYifuKpT3kTnF84mXeEQ84pJJZgyLBpU4FSkSwUkt/zbMyNAI7y5+jYTWGIg==", + "requires": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-metrics": "2.0.1" + } + }, + "@opentelemetry/exporter-prometheus": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.203.0.tgz", + "integrity": "sha512-2jLuNuw5m4sUj/SncDf/mFPabUxMZmmYetx5RKIMIQyPnl6G6ooFzfeE8aXNRf8YD1ZXNlCnRPcISxjveGJHNg==", + "requires": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-metrics": "2.0.1" + } + }, + "@opentelemetry/exporter-trace-otlp-grpc": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.203.0.tgz", + "integrity": "sha512-322coOTf81bm6cAA8+ML6A+m4r2xTCdmAZzGNTboPXRzhwPt4JEmovsFAs+grpdarObd68msOJ9FfH3jxM6wqA==", + "requires": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1" + } + }, + "@opentelemetry/exporter-trace-otlp-http": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.203.0.tgz", + "integrity": "sha512-ZDiaswNYo0yq/cy1bBLJFe691izEJ6IgNmkjm4C6kE9ub/OMQqDXORx2D2j8fzTBTxONyzusbaZlqtfmyqURPw==", + "requires": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1" + } + }, + "@opentelemetry/exporter-trace-otlp-proto": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.203.0.tgz", + "integrity": "sha512-1xwNTJ86L0aJmWRwENCJlH4LULMG2sOXWIVw+Szta4fkqKVY50Eo4HoVKKq6U9QEytrWCr8+zjw0q/ZOeXpcAQ==", + "requires": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1" + } }, - "@esbuild/freebsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", - "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", - "dev": true, - "optional": true + "@opentelemetry/exporter-zipkin": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.0.1.tgz", + "integrity": "sha512-a9eeyHIipfdxzCfc2XPrE+/TI3wmrZUDFtG2RRXHSbZZULAny7SyybSvaDvS77a7iib5MPiAvluwVvbGTsHxsw==", + "requires": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + } }, - "@esbuild/linux-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", - "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", - "dev": true, - "optional": true + "@opentelemetry/instrumentation": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.203.0.tgz", + "integrity": "sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ==", + "requires": { + "@opentelemetry/api-logs": "0.203.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1" + } }, - "@esbuild/linux-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", - "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", - "dev": true, - "optional": true + "@opentelemetry/instrumentation-http": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.203.0.tgz", + "integrity": "sha512-y3uQAcCOAwnO6vEuNVocmpVzG3PER6/YZqbPbbffDdJ9te5NkHEkfSMNzlC3+v7KlE+WinPGc3N7MR30G1HY2g==", + "requires": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/instrumentation": "0.203.0", + "@opentelemetry/semantic-conventions": "^1.29.0", + "forwarded-parse": "2.1.2" + } }, - "@esbuild/linux-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", - "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", - "dev": true, - "optional": true + "@opentelemetry/instrumentation-undici": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.14.0.tgz", + "integrity": "sha512-2HN+7ztxAReXuxzrtA3WboAKlfP5OsPA57KQn2AdYZbJ3zeRPcLXyW4uO/jpLE6PLm0QRtmeGCmfYpqRlwgSwg==", + "requires": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.203.0" + } }, - "@esbuild/linux-loong64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", - "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", - "dev": true, - "optional": true + "@opentelemetry/otlp-exporter-base": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.203.0.tgz", + "integrity": "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==", + "requires": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-transformer": "0.203.0" + } }, - "@esbuild/linux-mips64el": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", - "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", - "dev": true, - "optional": true + "@opentelemetry/otlp-grpc-exporter-base": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.203.0.tgz", + "integrity": "sha512-te0Ze1ueJF+N/UOFl5jElJW4U0pZXQ8QklgSfJ2linHN0JJsuaHG8IabEUi2iqxY8ZBDlSiz1Trfv5JcjWWWwQ==", + "requires": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/otlp-exporter-base": "0.203.0", + "@opentelemetry/otlp-transformer": "0.203.0" + } }, - "@esbuild/linux-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", - "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", - "dev": true, - "optional": true + "@opentelemetry/otlp-transformer": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.203.0.tgz", + "integrity": "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==", + "requires": { + "@opentelemetry/api-logs": "0.203.0", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-logs": "0.203.0", + "@opentelemetry/sdk-metrics": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1", + "protobufjs": "^7.3.0" + } }, - "@esbuild/linux-riscv64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", - "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", - "dev": true, - "optional": true + "@opentelemetry/propagator-b3": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-2.0.1.tgz", + "integrity": "sha512-Hc09CaQ8Tf5AGLmf449H726uRoBNGPBL4bjr7AnnUpzWMvhdn61F78z9qb6IqB737TffBsokGAK1XykFEZ1igw==", + "requires": { + "@opentelemetry/core": "2.0.1" + } }, - "@esbuild/linux-s390x": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", - "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", - "dev": true, - "optional": true + "@opentelemetry/propagator-jaeger": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.0.1.tgz", + "integrity": "sha512-7PMdPBmGVH2eQNb/AtSJizQNgeNTfh6jQFqys6lfhd6P4r+m/nTh3gKPPpaCXVdRQ+z93vfKk+4UGty390283w==", + "requires": { + "@opentelemetry/core": "2.0.1" + } }, - "@esbuild/linux-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", - "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", - "dev": true, - "optional": true + "@opentelemetry/resources": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz", + "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==", + "requires": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + } }, - "@esbuild/netbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", - "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", - "dev": true, - "optional": true + "@opentelemetry/sdk-logs": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz", + "integrity": "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==", + "requires": { + "@opentelemetry/api-logs": "0.203.0", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1" + } }, - "@esbuild/netbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", - "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", - "dev": true, - "optional": true + "@opentelemetry/sdk-metrics": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz", + "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==", + "requires": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1" + } }, - "@esbuild/openbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", - "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", - "dev": true, - "optional": true + "@opentelemetry/sdk-node": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.203.0.tgz", + "integrity": "sha512-zRMvrZGhGVMvAbbjiNQW3eKzW/073dlrSiAKPVWmkoQzah9wfynpVPeL55f9fVIm0GaBxTLcPeukWGy0/Wj7KQ==", + "requires": { + "@opentelemetry/api-logs": "0.203.0", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/exporter-logs-otlp-grpc": "0.203.0", + "@opentelemetry/exporter-logs-otlp-http": "0.203.0", + "@opentelemetry/exporter-logs-otlp-proto": "0.203.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "0.203.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", + "@opentelemetry/exporter-metrics-otlp-proto": "0.203.0", + "@opentelemetry/exporter-prometheus": "0.203.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.203.0", + "@opentelemetry/exporter-trace-otlp-http": "0.203.0", + "@opentelemetry/exporter-trace-otlp-proto": "0.203.0", + "@opentelemetry/exporter-zipkin": "2.0.1", + "@opentelemetry/instrumentation": "0.203.0", + "@opentelemetry/propagator-b3": "2.0.1", + "@opentelemetry/propagator-jaeger": "2.0.1", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-logs": "0.203.0", + "@opentelemetry/sdk-metrics": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1", + "@opentelemetry/sdk-trace-node": "2.0.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + } }, - "@esbuild/openbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", - "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", - "dev": true, - "optional": true + "@opentelemetry/sdk-trace-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz", + "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==", + "requires": { + "@opentelemetry/core": "2.0.1", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + } }, - "@esbuild/openharmony-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", - "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", - "dev": true, - "optional": true + "@opentelemetry/sdk-trace-node": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.0.1.tgz", + "integrity": "sha512-UhdbPF19pMpBtCWYP5lHbTogLWx9N0EBxtdagvkn5YtsAnCBZzL7SjktG+ZmupRgifsHMjwUaCCaVmqGfSADmA==", + "requires": { + "@opentelemetry/context-async-hooks": "2.0.1", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/sdk-trace-base": "2.0.1" + } }, - "@esbuild/sunos-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", - "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", - "dev": true, - "optional": true + "@opentelemetry/semantic-conventions": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.36.0.tgz", + "integrity": "sha512-TtxJSRD8Ohxp6bKkhrm27JRHAxPczQA7idtcTOMYI+wQRRrfgqxHv1cFbCApcSnNjtXkmzFozn6jQtFrOmbjPQ==" + }, + "@platformatic/basic": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@platformatic/basic/-/basic-3.52.0.tgz", + "integrity": "sha512-wXn4/Y6kSr11iXOIsEbCBEfWXm23FdK++y8bJ07MqnakERn9Riac2IIXgZm8QHDWbUHWDrQBQBdEqWsg//3luA==", + "requires": { + "@fastify/error": "^4.0.0", + "@platformatic/foundation": "3.52.0", + "@platformatic/itc": "3.52.0", + "@platformatic/metrics": "3.52.0", + "@platformatic/telemetry": "3.52.0", + "execa": "^9.3.1", + "fast-json-patch": "^3.1.1", + "pino": "^9.9.0", + "pino-abstract-transport": "^2.0.0", + "semver": "^7.6.3", + "split2": "^4.2.0", + "undici": "^7.0.0", + "ws": "^8.18.0" + } + }, + "@platformatic/control": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@platformatic/control/-/control-3.52.0.tgz", + "integrity": "sha512-hZmOnOcoe2/QjrdXUHMrVwb4Nqp/Ba2yXqffz/QCPT1IZ1zAmG28bNYX3PLWFZ+h+TkALU5onHVQjm1Hu7pNzQ==", + "requires": { + "@fastify/error": "^4.0.0", + "@platformatic/foundation": "3.52.0", + "help-me": "^5.0.0", + "pino": "^9.9.0", + "pino-pretty": "^13.0.0", + "table": "^6.8.1", + "undici": "^7.0.0", + "ws": "^8.16.0" + } + }, + "@platformatic/generators": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@platformatic/generators/-/generators-3.52.0.tgz", + "integrity": "sha512-J+0bs9vce+PGpyzVTwAnVWiXrjEItAYxX7bhzVVX0P0u0BXERi0sy0bklKjBR5tuY16NnteLczuAk0V6xk07/A==", + "requires": { + "@fastify/error": "^4.0.0", + "@platformatic/foundation": "3.52.0", + "change-case-all": "^2.1.0", + "execa": "^9.6.0", + "fastify": "^5.7.0", + "pino": "^9.9.0", + "undici": "^7.0.0" + } + }, + "@platformatic/itc": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@platformatic/itc/-/itc-3.52.0.tgz", + "integrity": "sha512-XwkT/9K5Mk6Br7xDqH9Zpun73n9GwIiIDEXJXgXPzq0Ek2IvUtaSDhWh02WiCIEvIHHFWXHauTd5olkL8eePbg==", + "requires": { + "@fastify/error": "^4.0.0", + "@watchable/unpromise": "^1.0.2" + } + }, + "@platformatic/metrics": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@platformatic/metrics/-/metrics-3.52.0.tgz", + "integrity": "sha512-uFCWl1l/0WGtlhmwVQmb4c4ozCZl0xiDuskuZd//xYslhX+UUxs5XGVqFAr4PYJuYQyjooOs22WyXcqX6564xQ==", + "requires": { + "@platformatic/http-metrics": "^0.3.0", + "@platformatic/prom-client": "^1.0.0", + "@platformatic/promotel": "^0.1.0" + } + }, + "@platformatic/runtime": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@platformatic/runtime/-/runtime-3.52.0.tgz", + "integrity": "sha512-/aC8MafEm6dornRlPZoaLlPGHfs/K1JLHgdg1zoC/yg6DpPfo/6MopD2hEb9Hm3aHdTJolmSZ77yzpS2sOes9Q==", + "requires": { + "@fastify/accepts": "^5.0.0", + "@fastify/basic-auth": "^6.0.0", + "@fastify/error": "^4.0.0", + "@fastify/websocket": "^11.0.0", + "@opentelemetry/api": "^1.9.0", + "@platformatic/basic": "3.52.0", + "@platformatic/foundation": "3.52.0", + "@platformatic/generators": "3.52.0", + "@platformatic/itc": "3.52.0", + "@platformatic/metrics": "3.52.0", + "@platformatic/prom-client": "^1.0.0", + "@platformatic/telemetry": "3.52.0", + "@platformatic/undici-cache-memory": "^0.8.1", + "@watchable/unpromise": "^1.0.2", + "change-case-all": "^2.1.0", + "close-with-grace": "^2.3.0", + "colorette": "^2.0.20", + "cron": "^4.1.0", + "debounce": "^2.0.0", + "fastest-levenshtein": "^1.0.16", + "fastify": "^5.7.0", + "graphql": "^16.8.1", + "help-me": "^5.0.0", + "minimist": "^1.2.8", + "pino": "^10.1.0", + "pino-opentelemetry-transport": "^2.0.0", + "pino-pretty": "^13.0.0", + "semgrator": "^0.3.0", + "sonic-boom": "^4.2.0", + "systeminformation": "^5.27.11", + "undici": "^7.0.0", + "undici-thread-interceptor": "^1.3.1", + "ws": "^8.16.0" + }, + "dependencies": { + "pino": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/pino/-/pino-10.3.1.tgz", + "integrity": "sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==", + "requires": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^3.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^4.0.0" + } + }, + "pino-abstract-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", + "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", + "requires": { + "split2": "^4.0.0" + } + }, + "pino-opentelemetry-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-opentelemetry-transport/-/pino-opentelemetry-transport-2.0.0.tgz", + "integrity": "sha512-tWoq02WEtnCWfr63Co1n0sGlDpkBz2YUovSAsSBv/+jwKUIn/PjxwRileGViKrH/K3e+oc71nGl6yUdgQlrVkg==", + "requires": { + "otlp-logger": "^1.1.4", + "pino-abstract-transport": "^3.0.0" + } + }, + "thread-stream": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.2.0.tgz", + "integrity": "sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ==", + "requires": { + "real-require": "^1.0.0" + }, + "dependencies": { + "real-require": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-1.0.0.tgz", + "integrity": "sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g==" + } + } + } + } + }, + "@platformatic/telemetry": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@platformatic/telemetry/-/telemetry-3.52.0.tgz", + "integrity": "sha512-QVdy0L0mDnRRhO5w1PJVMaZyx0TluLrN6pe8Lpsu7qBkfoAhxplGMDfxrscu7yXhnNur4X4U4IGGk0Vm5yiDkA==", + "requires": { + "@fastify/swagger": "^9.5.1", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/core": "^2.0.1", + "@opentelemetry/exporter-trace-otlp-proto": "^0.203.0", + "@opentelemetry/exporter-zipkin": "^2.0.1", + "@opentelemetry/instrumentation": "^0.203.0", + "@opentelemetry/instrumentation-http": "^0.203.0", + "@opentelemetry/instrumentation-undici": "^0.14.0", + "@opentelemetry/resources": "^2.0.1", + "@opentelemetry/sdk-node": "^0.203.0", + "@opentelemetry/sdk-trace-base": "^2.0.1", + "@opentelemetry/semantic-conventions": "1.36.0", + "@platformatic/foundation": "3.52.0", + "fast-uri": "^3.0.6", + "fastify-plugin": "^5.0.1" + } }, - "@esbuild/win32-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", - "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", - "dev": true, - "optional": true + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" }, - "@esbuild/win32-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", - "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", - "dev": true, - "optional": true + "import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "requires": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } }, - "@esbuild/win32-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", - "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", - "dev": true, - "optional": true + "otlp-logger": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/otlp-logger/-/otlp-logger-1.1.13.tgz", + "integrity": "sha512-r53tPnMLprtQSMOJUkj4Az4tR8NL+U+8C7M8BV1ZA9y7cDfAbWQp2mRL/eYS/O786oAi9KnN9hKsZ5cFKNchKw==", + "requires": { + "@opentelemetry/api-logs": "^0.206.0", + "@opentelemetry/exporter-logs-otlp-grpc": "^0.206.0", + "@opentelemetry/exporter-logs-otlp-http": "^0.206.0", + "@opentelemetry/exporter-logs-otlp-proto": "^0.206.0", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/sdk-logs": "^0.206.0" + }, + "dependencies": { + "@opentelemetry/api-logs": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.206.0.tgz", + "integrity": "sha512-yIVDu9jX//nV5wSMLZLdHdb1SKHIMj9k+wQVFtln5Flcgdldz9BkHtavvExQiJqBZg2OpEEJEZmzQazYztdz2A==", + "requires": { + "@opentelemetry/api": "^1.3.0" + } + }, + "@opentelemetry/core": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.1.0.tgz", + "integrity": "sha512-RMEtHsxJs/GiHHxYT58IY57UXAQTuUnZVco6ymDEqTNlJKTimM4qPUPVe8InNFyBjhHBEAx4k3Q8LtNayBsbUQ==", + "requires": { + "@opentelemetry/semantic-conventions": "^1.29.0" + } + }, + "@opentelemetry/exporter-logs-otlp-grpc": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.206.0.tgz", + "integrity": "sha512-kJKxKBaGwqWop95d6tcluz260IWwIgOG0BH8oVm6429tg8LxY2PJb7Om8d5s+5vOFM8DkUYCnIpn9d/13/RcKQ==", + "requires": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.1.0", + "@opentelemetry/otlp-exporter-base": "0.206.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.206.0", + "@opentelemetry/otlp-transformer": "0.206.0", + "@opentelemetry/sdk-logs": "0.206.0" + } + }, + "@opentelemetry/exporter-logs-otlp-http": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.206.0.tgz", + "integrity": "sha512-VWcHEnS+1kN+sQTAdCgSn2anqHPxY1/e52fhpe2mcSnEaXI1srFf3RU5DAu7hzQO6T9DPQzOKG8kc76vCtyYDw==", + "requires": { + "@opentelemetry/api-logs": "0.206.0", + "@opentelemetry/core": "2.1.0", + "@opentelemetry/otlp-exporter-base": "0.206.0", + "@opentelemetry/otlp-transformer": "0.206.0", + "@opentelemetry/sdk-logs": "0.206.0" + } + }, + "@opentelemetry/exporter-logs-otlp-proto": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.206.0.tgz", + "integrity": "sha512-CsYNXJwkn1qCXJGE+/JvvYucAjL8rpaxa2hnl+tDP6M5E0O3UVa8zG4ZUEebjr5J5Nc32egvslEZx5rgNOp3lQ==", + "requires": { + "@opentelemetry/api-logs": "0.206.0", + "@opentelemetry/core": "2.1.0", + "@opentelemetry/otlp-exporter-base": "0.206.0", + "@opentelemetry/otlp-transformer": "0.206.0", + "@opentelemetry/resources": "2.1.0", + "@opentelemetry/sdk-logs": "0.206.0", + "@opentelemetry/sdk-trace-base": "2.1.0" + } + }, + "@opentelemetry/otlp-exporter-base": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.206.0.tgz", + "integrity": "sha512-Rv54oSNKMHYS5hv+H5EGksfBUtvPQWFTK+Dk6MjJun9tOijCsFJrhRFvAqg5d67TWSMn+ZQYRKIeXh5oLVrpAQ==", + "requires": { + "@opentelemetry/core": "2.1.0", + "@opentelemetry/otlp-transformer": "0.206.0" + } + }, + "@opentelemetry/otlp-grpc-exporter-base": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.206.0.tgz", + "integrity": "sha512-IA8EDbrB8OKtidMqErBY8sUc9mh03LOXuNPwp4/rdPrxSt45g1gBuZMovRXdEWfRyKKbF2E7MdipT2m11bs6SQ==", + "requires": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "2.1.0", + "@opentelemetry/otlp-exporter-base": "0.206.0", + "@opentelemetry/otlp-transformer": "0.206.0" + } + }, + "@opentelemetry/otlp-transformer": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.206.0.tgz", + "integrity": "sha512-Li2Cik1WnmNbU2mmTnw7DxvRiXhMcnAuTfAclP8y/zy7h5+GrLDpTZ+Z0XUs+Q3MLkb/h3ry4uFrC/z+2a6X7g==", + "requires": { + "@opentelemetry/api-logs": "0.206.0", + "@opentelemetry/core": "2.1.0", + "@opentelemetry/resources": "2.1.0", + "@opentelemetry/sdk-logs": "0.206.0", + "@opentelemetry/sdk-metrics": "2.1.0", + "@opentelemetry/sdk-trace-base": "2.1.0", + "protobufjs": "^7.3.0" + } + }, + "@opentelemetry/resources": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.1.0.tgz", + "integrity": "sha512-1CJjf3LCvoefUOgegxi8h6r4B/wLSzInyhGP2UmIBYNlo4Qk5CZ73e1eEyWmfXvFtm1ybkmfb2DqWvspsYLrWw==", + "requires": { + "@opentelemetry/core": "2.1.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + } + }, + "@opentelemetry/sdk-logs": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.206.0.tgz", + "integrity": "sha512-SQ2yTmqe4Mw9RI3a/glVkfjWPsXh6LySvnljXubiZq4zu+UP8NMJt2j82ZsYb+KpD7Eu+/41/7qlJnjdeVjz7Q==", + "requires": { + "@opentelemetry/api-logs": "0.206.0", + "@opentelemetry/core": "2.1.0", + "@opentelemetry/resources": "2.1.0" + } + }, + "@opentelemetry/sdk-metrics": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.1.0.tgz", + "integrity": "sha512-J9QX459mzqHLL9Y6FZ4wQPRZG4TOpMCyPOh6mkr/humxE1W2S3Bvf4i75yiMW9uyed2Kf5rxmLhTm/UK8vNkAw==", + "requires": { + "@opentelemetry/core": "2.1.0", + "@opentelemetry/resources": "2.1.0" + } + }, + "@opentelemetry/sdk-trace-base": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.1.0.tgz", + "integrity": "sha512-uTX9FBlVQm4S2gVQO1sb5qyBLq/FPjbp+tmGoxu4tIgtYGmBYB44+KX/725RFDe30yBSaA9Ml9fqphe1hbUyLQ==", + "requires": { + "@opentelemetry/core": "2.1.0", + "@opentelemetry/resources": "2.1.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + } + } + } }, - "esbuild": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", - "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", - "dev": true, + "pino": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", + "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==", "requires": { - "@esbuild/aix-ppc64": "0.27.7", - "@esbuild/android-arm": "0.27.7", - "@esbuild/android-arm64": "0.27.7", - "@esbuild/android-x64": "0.27.7", - "@esbuild/darwin-arm64": "0.27.7", - "@esbuild/darwin-x64": "0.27.7", - "@esbuild/freebsd-arm64": "0.27.7", - "@esbuild/freebsd-x64": "0.27.7", - "@esbuild/linux-arm": "0.27.7", - "@esbuild/linux-arm64": "0.27.7", - "@esbuild/linux-ia32": "0.27.7", - "@esbuild/linux-loong64": "0.27.7", - "@esbuild/linux-mips64el": "0.27.7", - "@esbuild/linux-ppc64": "0.27.7", - "@esbuild/linux-riscv64": "0.27.7", - "@esbuild/linux-s390x": "0.27.7", - "@esbuild/linux-x64": "0.27.7", - "@esbuild/netbsd-arm64": "0.27.7", - "@esbuild/netbsd-x64": "0.27.7", - "@esbuild/openbsd-arm64": "0.27.7", - "@esbuild/openbsd-x64": "0.27.7", - "@esbuild/openharmony-arm64": "0.27.7", - "@esbuild/sunos-x64": "0.27.7", - "@esbuild/win32-arm64": "0.27.7", - "@esbuild/win32-ia32": "0.27.7", - "@esbuild/win32-x64": "0.27.7" + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" } - } - } - }, - "tus-js-client": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-4.3.1.tgz", - "integrity": "sha512-ZLeYmjrkaU1fUsKbIi8JML52uAocjEZtBx4DKjRrqzrZa0O4MYwT6db+oqePlspV+FxXJAyFBc/L5gwUi2OFsg==", - "dev": true, - "requires": { - "buffer-from": "^1.1.2", - "combine-errors": "^3.0.3", - "is-stream": "^2.0.0", - "js-base64": "^3.7.2", - "lodash.throttle": "^4.1.1", - "proper-lockfile": "^4.1.2", - "url-parse": "^1.5.7" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" - }, - "typed-emitter": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-0.1.0.tgz", - "integrity": "sha512-Tfay0l6gJMP5rkil8CzGbLthukn+9BN/VXWcABVFPjOoelJ+koW8BuPZYk+h/L+lEeIp1fSzVRiWRPIjKVjPdg==" - }, - "typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true - }, - "undici": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.6.tgz", - "integrity": "sha512-Xi4agocCbRzt0yYMZGMA6ApD7gvtUFaxm4ZmeacWI4cZxaF6C+8I8QfofC20NAePiB/IcvZmzkJ7XPa471AEtA==" - }, - "undici-thread-interceptor": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/undici-thread-interceptor/-/undici-thread-interceptor-1.3.1.tgz", - "integrity": "sha512-s/TUkGeVj+C4Rr3Vsy84Kewj97m2QBNx6IjMGM1nzfoKWqNlcLqtFQCbXQjobRJQKi3u9Hc796/YvJIv7W7qWQ==", - "requires": { - "fastq": "^1.19.1", - "hyperid": "^3.2.0", - "light-my-request": "^6.5.1", - "undici": "^7.0.0" - } - }, - "undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==" - }, - "unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==" - }, - "url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "uuid-parse": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/uuid-parse/-/uuid-parse-1.1.0.tgz", - "integrity": "sha512-OdmXxA8rDsQ7YpNVbKSJkNzTw2I+S5WsbMDnCtIWSQaosNAcWtFuI/YK1TjzUI6nbkgiqEyh8gWngfcv8Asd9A==" - }, - "vitest": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.5.tgz", - "integrity": "sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==", - "dev": true, - "requires": { - "@vitest/expect": "4.1.5", - "@vitest/mocker": "4.1.5", - "@vitest/pretty-format": "4.1.5", - "@vitest/runner": "4.1.5", - "@vitest/snapshot": "4.1.5", - "@vitest/spy": "4.1.5", - "@vitest/utils": "4.1.5", - "es-module-lexer": "^2.0.0", - "expect-type": "^1.3.0", - "magic-string": "^0.30.21", - "obug": "^2.1.1", - "pathe": "^2.0.3", - "picomatch": "^4.0.3", - "std-env": "^4.0.0-rc.1", - "tinybench": "^2.9.0", - "tinyexec": "^1.0.2", - "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.1.0", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", - "why-is-node-running": "^2.3.0" - }, - "dependencies": { - "@vitest/mocker": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.5.tgz", - "integrity": "sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==", - "dev": true, + }, + "pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", "requires": { - "@vitest/spy": "4.1.5", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.21" + "split2": "^4.0.0" } }, - "picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true + "require-in-the-middle": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", + "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", + "requires": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.8" + } }, - "vite": { - "version": "8.0.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.10.tgz", - "integrity": "sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==", - "dev": true, + "thread-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz", + "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==", "requires": { - "fsevents": "~2.3.3", - "lightningcss": "^1.32.0", - "picomatch": "^4.0.4", - "postcss": "^8.5.10", - "rolldown": "1.0.0-rc.17", - "tinyglobby": "^0.2.16" + "real-require": "^0.2.0" } } } }, - "wattpm": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/wattpm/-/wattpm-3.52.0.tgz", - "integrity": "sha512-Lm8wkRLxjWkfKEXaAt2B6R5jeZ1GIt4UKCDL9sx+zS+lVd5r600kOvZ93sTFGzGetaD/ENXJtY35r6/YccEWIw==", - "requires": { - "@fastify/websocket": "^11.0.0", - "@platformatic/control": "3.52.0", - "@platformatic/foundation": "3.52.0", - "@platformatic/runtime": "3.52.0", - "colorette": "^2.0.20", - "pino-pretty": "^13.0.0", - "split2": "^4.2.0", - "table": "^6.8.2" - }, - "dependencies": { - "colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" - } - } - }, "web-streams-polyfill": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", diff --git a/package.json b/package.json index 0f6836b8e..c873d021d 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "test:integration:watch": "vitest --config vitest.integration.config.ts", "test:integration:coverage": "vitest run --coverage --config vitest.integration.config.ts", "acceptance": "tsx acceptance/scripts/run-managed-local.ts", + "acceptance:watt": "tsx acceptance/scripts/run-managed-watt-local.ts", "acceptance:run": "tsx acceptance/scripts/run.ts", "acceptance:typecheck": "tsc -p acceptance/tsconfig.json --noEmit", "test": "npm run test:unit && npm run infra:restart && npm run test:dummy-data && npm run test:integration", @@ -75,11 +76,11 @@ "@opentelemetry/instrumentation-runtime-node": "^0.25.0", "@opentelemetry/sdk-metrics": "^2.6.1", "@opentelemetry/sdk-node": "^0.213.0", - "@platformatic/control": "^3.52.0", + "@platformatic/control": "^3.56.0", "@platformatic/flame": "^1.6.0", - "@platformatic/globals": "^3.52.0", - "@platformatic/node": "^3.52.0", - "@platformatic/wattpm-pprof-capture": "^3.52.1", + "@platformatic/globals": "^3.56.0", + "@platformatic/node": "^3.56.0", + "@platformatic/wattpm-pprof-capture": "^3.56.0", "@shopify/semaphore": "^3.0.2", "@smithy/node-http-handler": "^2.3.1", "@tus/file-store": "2.0.0", @@ -116,6 +117,7 @@ "devDependencies": { "@aws-sdk/s3-presigned-post": "^3.1023.0", "@biomejs/biome": "^2.4.4", + "@platformatic/runtime": "^3.56.0", "@types/async-retry": "^1.4.5", "@types/js-yaml": "^4.0.5", "@types/json-bigint": "^1.0.4", diff --git a/src/admin-app.test.ts b/src/admin-app.test.ts index 94881bbb1..9a443e69c 100644 --- a/src/admin-app.test.ts +++ b/src/admin-app.test.ts @@ -1,23 +1,78 @@ import { vi } from 'vitest' -const getGlobal = vi.hoisted(() => vi.fn()) - -vi.mock('@platformatic/globals', () => ({ - getGlobal, -})) +function mockAdminAppDependencies() { + vi.doMock('./config', () => ({ + getConfig: () => ({ + prometheusMetricsEnabled: false, + version: 'test', + }), + })) + vi.doMock('@internal/monitoring/otel-metrics', () => ({ + handleMetricsRequest: vi.fn(), + })) + vi.doMock('./http', () => ({ + plugins: { + adminTenantId: async () => {}, + logRequest: () => async () => {}, + requestContext: async () => {}, + signals: async () => {}, + }, + routes: { + jwks: async () => {}, + metricsConfig: async () => {}, + migrations: async () => {}, + objects: async () => {}, + pprof: async (fastify: { get: Function }) => { + fastify.get('/profile', async (_request: unknown, reply: { status: Function }) => { + return reply.status(401).send() + }) + }, + queue: async () => {}, + s3Credentials: async () => {}, + tenants: async () => {}, + }, + setErrorHandler: vi.fn(), + })) +} async function buildAdminApp() { - vi.resetModules() + mockAdminAppDependencies() const { default: buildAdmin } = await import('./admin-app') const app = buildAdmin({}) await app.ready() return app } +async function clearWattGlobals() { + const { removeGlobals } = await import('@platformatic/globals') + removeGlobals(['applicationId', 'workerId', 'messaging']) +} + +async function setWattGlobals() { + const { updateGlobals } = await import('@platformatic/globals') + updateGlobals({ + applicationId: 'storage', + workerId: 0, + }) +} + describe('admin app pprof registration', () => { - it('does not register pprof endpoints outside Watt', async () => { - getGlobal.mockReturnValue(undefined) + beforeEach(async () => { + vi.useRealTimers() + vi.resetModules() + await clearWattGlobals() + }) + afterEach(async () => { + vi.useRealTimers() + await clearWattGlobals() + vi.doUnmock('./config') + vi.doUnmock('@internal/monitoring/otel-metrics') + vi.doUnmock('./http') + vi.resetModules() + }) + + it('does not register pprof endpoints outside Watt', async () => { const app = await buildAdminApp() try { @@ -33,10 +88,7 @@ describe('admin app pprof registration', () => { }) it('registers pprof endpoints under Watt', async () => { - getGlobal.mockReturnValue({ - applicationId: 'storage', - workerId: 0, - }) + await setWattGlobals() const app = await buildAdminApp() diff --git a/src/admin-app.ts b/src/admin-app.ts index 6dbb898ac..d40f3b912 100644 --- a/src/admin-app.ts +++ b/src/admin-app.ts @@ -1,7 +1,7 @@ import fastifySwagger from '@fastify/swagger' import fastifySwaggerUi from '@fastify/swagger-ui' import { handleMetricsRequest } from '@internal/monitoring/otel-metrics' -import { getGlobal } from '@platformatic/globals' +import { hasField } from '@platformatic/globals' import fastify, { FastifyInstance, FastifyServerOptions } from 'fastify' import { getConfig } from './config' import { plugins, routes, setErrorHandler } from './http' @@ -14,7 +14,7 @@ const { version, prometheusMetricsEnabled } = getConfig() const build = (opts: buildOpts = {}): FastifyInstance => { const app = fastify(opts) - const isRunningUnderWatt = typeof getGlobal()?.applicationId === 'string' + const isRunningUnderWatt = hasField('applicationId') if (opts.exposeDocs) { app.register(fastifySwagger, { diff --git a/src/database/cancellation.ts b/src/database/cancellation.ts new file mode 100644 index 000000000..887c3330c --- /dev/null +++ b/src/database/cancellation.ts @@ -0,0 +1,132 @@ +import type { PoolClient } from 'pg' +import PgConnection from 'pg/lib/connection' + +export type CancellableClient = PoolClient & { + processID?: number + secretKey?: number + host?: string | string[] + port?: number + connectionParameters?: { + host?: string | string[] + port?: number + } +} + +export type InFlightOperation = { + client?: CancellableClient + lockId?: string + cancelled: boolean +} + +export class CancellationRegistry { + private readonly operations = new Map() + + start(requestId: string | undefined, operation: InFlightOperation): void { + if (requestId) { + this.operations.set(requestId, operation) + } + } + + setClient(requestId: string | undefined, client: CancellableClient): void { + if (!requestId) { + return + } + + const operation = this.operations.get(requestId) + if (operation) { + operation.client = client + } + } + + finish(requestId: string | undefined): void { + if (requestId) { + this.operations.delete(requestId) + } + } + + async cancel(requestId: string, lockId?: string): Promise<{ cancelled: boolean }> { + const operation = this.operations.get(requestId) + if (!operation) { + return { cancelled: false } + } + + if (lockId && operation.lockId && operation.lockId !== lockId) { + return { cancelled: false } + } + + operation.cancelled = true + if (operation.client) { + await cancelPgQuery(operation.client) + } + + return { cancelled: true } + } +} + +async function cancelPgQuery(client: CancellableClient): Promise { + const processID = client.processID + const secretKey = client.secretKey + + if (!processID || !secretKey) { + return + } + + const cancelConnection = new PgConnection() + cancelConnection.unref() + const target = getPgCancelConnectionTarget(client) + + return new Promise((resolve) => { + let resolved = false + + const done = () => { + if (resolved) { + return + } + + resolved = true + clearTimeout(timeout) + cancelConnection.end() + resolve() + } + + const timeout = setTimeout(done, 5_000) + timeout.unref() + + cancelConnection.on('error', done) + cancelConnection.on('end', done) + cancelConnection.on('connect', () => { + try { + cancelConnection.cancel(processID, secretKey) + } catch { + done() + } + }) + + if (target.type === 'socket') { + cancelConnection.connect(target.path) + } else { + cancelConnection.connect(target.port, target.host) + } + }) +} + +function getPgCancelConnectionTarget( + client: Pick +): { type: 'socket'; path: string } | { type: 'tcp'; host: string; port: number } { + const rawHost = client.host || client.connectionParameters?.host || 'localhost' + const host = Array.isArray(rawHost) ? rawHost[0] || 'localhost' : rawHost + const port = client.port || client.connectionParameters?.port || 5432 + + if (host.startsWith('/')) { + return { + type: 'socket', + path: `${host}/.s.PGSQL.${port}`, + } + } + + return { + type: 'tcp', + host, + port, + } +} diff --git a/src/database/config.ts b/src/database/config.ts new file mode 100644 index 000000000..3a6601193 --- /dev/null +++ b/src/database/config.ts @@ -0,0 +1,111 @@ +import { readFileSync } from 'node:fs' + +export type DatabaseConfig = { + applicationName: string + acquireTimeoutMs: number + connectionTimeoutMs: number + destinationAcquireQueueLimit: number + destinationMaxConnections: number + globalAcquireQueueLimit: number + globalMaxConnections: number + idlePoolTimeoutMs: number + lockIdleTimeoutMs: number + lockMaxLifetimeMs: number + masterIsExternalPool: boolean + masterConnectionString?: string + masterMaxConnections: number + maxActivePools: number + maxOperationNameLength: number + maxParameterCount: number + maxRequestIdLength: number + maxResultBytes: number + maxResultRows: number + maxSerializedRequestBytes: number + maxSqlBytes: number + poolConnectionString?: string + poolMode?: string + rootCert?: string + serverStatementTimeoutMs: number + shutdownTimeoutMs: number +} + +export function readConfig(env: NodeJS.ProcessEnv = process.env): DatabaseConfig { + return { + applicationName: env.DATABASE_APPLICATION_NAME || `Supabase Storage Database Watt`, + acquireTimeoutMs: readPositiveInteger(env.DATABASE_WATT_ACQUIRE_TIMEOUT, 3_000), + connectionTimeoutMs: readPositiveInteger(env.DATABASE_CONNECTION_TIMEOUT, 3_000), + destinationAcquireQueueLimit: readPositiveInteger( + env.DATABASE_WATT_DESTINATION_ACQUIRE_QUEUE_LIMIT, + 100 + ), + destinationMaxConnections: readPositiveInteger( + env.DATABASE_WATT_DESTINATION_MAX_CONNECTIONS || env.DATABASE_MAX_CONNECTIONS, + 20 + ), + globalAcquireQueueLimit: readPositiveInteger(env.DATABASE_WATT_GLOBAL_ACQUIRE_QUEUE_LIMIT, 500), + globalMaxConnections: readPositiveInteger( + env.DATABASE_WATT_GLOBAL_MAX_CONNECTIONS || env.DATABASE_MAX_CONNECTIONS, + 20 + ), + idlePoolTimeoutMs: readPositiveInteger( + env.DATABASE_WATT_POOL_IDLE_TIMEOUT || env.DATABASE_FREE_POOL_AFTER_INACTIVITY, + 60_000 + ), + lockIdleTimeoutMs: readPositiveInteger(env.DATABASE_WATT_LOCK_IDLE_TIMEOUT, 30_000), + lockMaxLifetimeMs: readPositiveInteger(env.DATABASE_WATT_LOCK_MAX_LIFETIME, 120_000), + masterConnectionString: + isTruthy(env.MULTI_TENANT) || isTruthy(env.IS_MULTITENANT) + ? env.DATABASE_MULTITENANT_POOL_URL || env.DATABASE_MULTITENANT_URL + : undefined, + masterIsExternalPool: Boolean(env.DATABASE_MULTITENANT_POOL_URL), + masterMaxConnections: readPositiveInteger( + env.DATABASE_MULTITENANT_MAX_CONNECTIONS || env.DATABASE_WATT_MASTER_MAX_CONNECTIONS, + 10 + ), + maxActivePools: readPositiveInteger(env.DATABASE_WATT_MAX_ACTIVE_POOLS, 1_000), + maxOperationNameLength: readPositiveInteger(env.DATABASE_WATT_MAX_OPERATION_NAME_LENGTH, 128), + maxParameterCount: readPositiveInteger(env.DATABASE_WATT_MAX_PARAMETER_COUNT, 10_000), + maxRequestIdLength: readPositiveInteger(env.DATABASE_WATT_MAX_REQUEST_ID_LENGTH, 128), + maxResultBytes: readPositiveInteger(env.DATABASE_WATT_MAX_RESULT_BYTES, 10 * 1024 * 1024), + maxResultRows: readPositiveInteger(env.DATABASE_WATT_MAX_RESULT_ROWS, 10_000), + maxSerializedRequestBytes: readPositiveInteger( + env.DATABASE_WATT_MAX_SERIALIZED_REQUEST_BYTES, + 10 * 1024 * 1024 + ), + maxSqlBytes: readPositiveInteger(env.DATABASE_WATT_MAX_SQL_BYTES, 1024 * 1024), + poolConnectionString: env.DATABASE_POOL_URL || env.DATABASE_URL, + poolMode: env.DATABASE_POOL_MODE, + rootCert: readRootCert(env.DATABASE_SSL_ROOT_CERT), + serverStatementTimeoutMs: readInteger(env.DATABASE_STATEMENT_TIMEOUT, 30_000), + shutdownTimeoutMs: readPositiveInteger(env.DATABASE_WATT_SHUTDOWN_TIMEOUT, 10_000), + } +} + +function readInteger(value: string | undefined, fallback: number): number { + if (value === undefined || value === '') { + return fallback + } + + const numberValue = Number.parseInt(value, 10) + return Number.isFinite(numberValue) ? numberValue : fallback +} + +function readPositiveInteger(value: string | undefined, fallback: number): number { + return Math.max(readInteger(value, fallback), 0) +} + +function readRootCert(value: string | undefined): string | undefined { + if (!value) { + return undefined + } + + if (value.includes('-----BEGIN CERTIFICATE-----')) { + return value + } + + return readFileSync(value, 'utf8') +} + +function isTruthy(value: string | undefined): boolean { + return value === '1' || value === 'true' || value === 'yes' +} diff --git a/src/database/destinations.ts b/src/database/destinations.ts new file mode 100644 index 000000000..fc5b3c182 --- /dev/null +++ b/src/database/destinations.ts @@ -0,0 +1,117 @@ +import { Pool } from 'pg' +import type { DatabaseConfig } from './config.js' +import { DatabaseWattError } from './errors.js' +import { getSslSettings } from './ssl.js' +import type { DestinationConfig } from './types.js' + +type TenantRow = { + database_pool_mode?: string | null + database_pool_url?: string | null + database_url: string + max_connections?: number | null +} + +export class DestinationResolver { + private masterPool?: Pool + private readonly config: DatabaseConfig + + constructor(config: DatabaseConfig) { + this.config = config + } + + async resolve(destination: string): Promise { + if (destination === 'master') { + return this.resolveMasterDestination() + } + + if (this.config.masterConnectionString) { + return this.resolveTenant(destination) + } + + const connectionString = this.config.poolConnectionString + if (!connectionString) { + throw new DatabaseWattError('DESTINATION_UNKNOWN', 'No database connection string configured') + } + + return { + connectionString, + id: destination, + isExternalPool: Boolean(process.env.DATABASE_POOL_URL), + maxConnections: this.config.destinationMaxConnections, + poolMode: this.config.poolMode, + } + } + + async close(): Promise { + const pool = this.masterPool + this.masterPool = undefined + if (pool) { + await pool.end() + } + } + + private async resolveTenant(destination: string): Promise { + const result = await this.getMasterPool().query( + ` + SELECT database_url, database_pool_url, database_pool_mode, max_connections + FROM tenants + WHERE id = $1 + LIMIT 1 + `, + [destination] + ) + + const tenant = result.rows[0] + if (!tenant) { + throw new DatabaseWattError('DESTINATION_UNKNOWN', 'Destination is unknown') + } + + const connectionString = tenant.database_pool_url || tenant.database_url + if (!connectionString) { + throw new DatabaseWattError('DESTINATION_UNKNOWN', 'Destination has no database credentials') + } + + return { + connectionString, + id: destination, + isExternalPool: Boolean(tenant.database_pool_url), + maxConnections: tenant.max_connections || this.config.destinationMaxConnections, + poolMode: tenant.database_pool_mode, + } + } + + private resolveMasterDestination(): DestinationConfig { + const connectionString = this.config.masterConnectionString + if (!connectionString) { + throw new DatabaseWattError('DESTINATION_UNKNOWN', 'No multitenant database configured') + } + + return { + connectionString, + id: 'master', + isExternalPool: this.config.masterIsExternalPool, + maxConnections: this.config.masterMaxConnections, + } + } + + private getMasterPool(): Pool { + const connectionString = this.config.masterConnectionString + if (!connectionString) { + throw new DatabaseWattError('DESTINATION_UNKNOWN', 'No multitenant database configured') + } + + if (!this.masterPool) { + this.masterPool = new Pool({ + application_name: this.config.applicationName, + connectionString, + connectionTimeoutMillis: this.config.connectionTimeoutMs, + idleTimeoutMillis: this.config.idlePoolTimeoutMs, + max: this.config.masterMaxConnections, + min: 0, + ssl: getSslSettings(connectionString, this.config.rootCert), + }) + } + + return this.masterPool + } +} diff --git a/src/database/errors.ts b/src/database/errors.ts new file mode 100644 index 000000000..e258faba1 --- /dev/null +++ b/src/database/errors.ts @@ -0,0 +1,117 @@ +import { DatabaseError } from 'pg' + +export type DatabaseErrorCode = + | 'POSTGRES_ERROR' + | 'DESTINATION_UNKNOWN' + | 'CLIENT_TIMEOUT' + | 'SERVER_TIMEOUT' + | 'CONNECTION_TIMEOUT' + | 'ACQUIRE_TIMEOUT' + | 'MESSAGING_TIMEOUT' + | 'MESSAGING_ERROR' + | 'BUSY' + | 'RESULT_TOO_LARGE' + | 'PROTOCOL_ERROR' + | 'SHUTDOWN' + +export type DatabaseErrorResponse = { + code: DatabaseErrorCode + message: string + requestId?: string + operationName?: string + destination?: string + lockId?: string + sqlState?: string + stack?: string + connectionDiscarded?: boolean +} + +export type ErrorContext = { + requestId?: string + operationName?: string + destination?: string + lockId?: string +} + +export class DatabaseWattError extends Error { + readonly code: DatabaseErrorCode + readonly connectionDiscarded?: boolean + readonly sqlState?: string + + constructor( + code: DatabaseErrorCode, + message: string, + options: { connectionDiscarded?: boolean; cause?: unknown; sqlState?: string } = {} + ) { + super(message, { cause: options.cause }) + this.name = 'DatabaseWattError' + this.code = code + this.connectionDiscarded = options.connectionDiscarded + this.sqlState = options.sqlState + } +} + +export function toErrorResponse(error: unknown, context: ErrorContext = {}): DatabaseErrorResponse { + if (error instanceof DatabaseWattError) { + return { + code: error.code, + message: error.message, + requestId: context.requestId, + operationName: context.operationName, + destination: context.destination, + lockId: context.lockId, + sqlState: error.sqlState, + stack: error.stack, + connectionDiscarded: error.connectionDiscarded, + } + } + + if (error instanceof DatabaseError) { + return { + code: 'POSTGRES_ERROR', + message: error.message, + requestId: context.requestId, + operationName: context.operationName, + destination: context.destination, + lockId: context.lockId, + sqlState: error.code, + stack: error.stack, + } + } + + if (isConnectionTimeoutError(error)) { + const connectionError = error as Error + return { + code: 'CONNECTION_TIMEOUT', + message: connectionError.message, + requestId: context.requestId, + operationName: context.operationName, + destination: context.destination, + lockId: context.lockId, + stack: connectionError.stack, + } + } + + const fallback = error instanceof Error ? error : new Error(String(error)) + return { + code: 'MESSAGING_ERROR', + message: fallback.message, + requestId: context.requestId, + operationName: context.operationName, + destination: context.destination, + lockId: context.lockId, + stack: fallback.stack, + } +} + +export function isErrorResponse(value: unknown): boolean { + return Boolean(value && typeof value === 'object' && 'code' in value && 'message' in value) +} + +function isConnectionTimeoutError(error: unknown): boolean { + return ( + error instanceof Error && + (error.message === 'timeout expired' || + error.message === 'timeout exceeded when trying to connect') + ) +} diff --git a/src/database/index.ts b/src/database/index.ts new file mode 100644 index 000000000..2bc0e2876 --- /dev/null +++ b/src/database/index.ts @@ -0,0 +1,346 @@ +import { getMessaging } from '@platformatic/globals' +import { CancellationRegistry } from './cancellation.js' +import { readConfig } from './config.js' +import { DestinationResolver } from './destinations.js' +import { DatabaseWattError, toErrorResponse } from './errors.js' +import { LockRegistry } from './locks.js' +import { registerDatabaseWattMetrics } from './metrics.js' +import { PoolRegistry, runQuery } from './pools.js' +import { enforceResultLimits } from './result-limits.js' +import type { + AcquireConnectionRequest, + BeginTransactionRequest, + CancelRequest, + CommitTransactionRequest, + LockedQueryRequest, + QueryRequest, + ReleaseConnectionRequest, + RollbackTransactionRequest, +} from './types.js' +import { + validateCancelRequest, + validateLockRequestEnvelope, + validateNonLockRequestEnvelope, + validateQueryEnvelope, +} from './validation.js' + +export class Application { + #config: ReturnType + #resolver: DestinationResolver + #pools: PoolRegistry + #locks: LockRegistry + #cancellations: CancellationRegistry + #shuttingDown: boolean + #stats: Record + + constructor() { + this.#config = readConfig() + this.#resolver = new DestinationResolver(this.#config) + this.#pools = new PoolRegistry(this.#config) + this.#locks = new LockRegistry(this.#config) + this.#cancellations = new CancellationRegistry() + this.#shuttingDown = false + this.#stats = { + acquire: 0, + beginTransaction: 0, + cancel: 0, + commitTransaction: 0, + lockedQuery: 0, + query: 0, + release: 0, + rollbackTransaction: 0, + } + + this.#registerHandlers() + registerDatabaseWattMetrics(this.#pools) + } + + close(): Promise { + this.#shuttingDown = true + + return this.#withShutdownTimeout( + Promise.allSettled([this.#locks.close(), this.#pools.close(), this.#resolver.close()]).then(() => undefined), + this.#config.shutdownTimeoutMs + ) + } + + #registerHandlers(): void { + const messaging = getMessaging({throwOnMissing: false}) + + if (!messaging) { + return + } + + messaging.handle('database.query', this.#handleQuery.bind(this)) + messaging.handle('database.acquire', this.#handleAcquire.bind(this)) + messaging.handle('database.lockedQuery', this.#handleLockedQuery.bind(this)) + messaging.handle('database.release', this.#handleRelease.bind(this)) + messaging.handle('database.beginTransaction', this.#handleBeginTransaction.bind(this)) + messaging.handle('database.commitTransaction', this.#handleCommitTransaction.bind(this)) + messaging.handle('database.rollbackTransaction', this.#handleRollbackTransaction.bind(this)) + messaging.handle('database.cancel', this.#handleCancel.bind(this)) + messaging.handle('database.test.stats', () => ({ ...this.#stats })) + messaging.handle('database.test.resetStats', this.#handleResetStats.bind(this)) + } + + async #handleQuery(rawRequest: unknown): Promise { + this.#stats.query++ + let request: QueryRequest | undefined + let cancellationRequestId: string | undefined + + try { + validateNonLockRequestEnvelope(rawRequest, this.#config) + validateQueryEnvelope(rawRequest, this.#config) + request = rawRequest as QueryRequest + + this.#assertAcceptingWork() + const destination = await this.#resolver.resolve(request.destination) + this.#cancellations.start(request.requestId, { cancelled: false }) + cancellationRequestId = request.requestId + + const response = await this.#pools.query( + destination, + request.sql, + request.values, + (client) => this.#cancellations.setClient(request?.requestId, client) + ) + return enforceResultLimits(response, this.#config) + } catch (error) { + return toErrorResponse(error, request ?? undefined) + } finally { + this.#cancellations.finish(cancellationRequestId) + } + } + + async #handleAcquire(rawRequest: unknown): Promise { + this.#stats.acquire++ + let request: AcquireConnectionRequest | undefined + + try { + validateNonLockRequestEnvelope(rawRequest, this.#config) + request = rawRequest as AcquireConnectionRequest + + this.#assertAcceptingWork() + const destination = await this.#resolver.resolve(request.destination) + const client = await this.#pools.acquire(destination) + return { lockId: this.#locks.create(destination, client) } + } catch (error) { + return toErrorResponse(error, request ?? undefined) + } + } + + async #handleLockedQuery(rawRequest: unknown): Promise { + this.#stats.lockedQuery++ + let request: LockedQueryRequest | undefined + let context: LockedQueryRequest | (LockedQueryRequest & { destination?: string }) | undefined + let cancellationRequestId: string | undefined + + try { + validateLockRequestEnvelope(rawRequest, this.#config) + validateQueryEnvelope(rawRequest, this.#config) + request = rawRequest as LockedQueryRequest + context = request + context = this.#withLockContext(request) + + this.#assertAcceptingWork() + this.#cancellations.start(request.requestId, { cancelled: false, lockId: request.lockId }) + cancellationRequestId = request.requestId + + this.#cancellations.setClient(request.requestId, this.#locks.getClient(request.lockId)) + const response = await this.#locks.query(request.lockId, request.sql, request.values) + return enforceResultLimits(response, this.#config) + } catch (error) { + return toErrorResponse(error, context ?? undefined) + } finally { + this.#cancellations.finish(cancellationRequestId) + } + } + + async #handleRelease(rawRequest: unknown): Promise { + this.#stats.release++ + let request: ReleaseConnectionRequest | undefined + let context: ReleaseConnectionRequest | (ReleaseConnectionRequest & { destination?: string }) | undefined + + try { + validateLockRequestEnvelope(rawRequest, this.#config) + request = rawRequest as ReleaseConnectionRequest + context = request + context = this.#withLockContext(request) + + await this.#locks.release(request.lockId) + return { released: true } + } catch (error) { + return toErrorResponse(error, context ?? undefined) + } + } + + async #handleBeginTransaction(rawRequest: unknown): Promise { + this.#stats.beginTransaction++ + let request: BeginTransactionRequest | undefined + + try { + validateNonLockRequestEnvelope(rawRequest, this.#config) + request = rawRequest as BeginTransactionRequest + + this.#assertAcceptingWork() + const destination = await this.#resolver.resolve(request.destination) + const client = await this.#pools.acquire(destination) + let lockId: string | undefined + + try { + await runQuery(client, this.#buildBeginStatement(request)) + if (this.#config.serverStatementTimeoutMs > 0) { + await runQuery(client, `SELECT set_config('statement_timeout', $1, true)`, [ + `${this.#config.serverStatementTimeoutMs}ms`, + ]) + } + lockId = this.#locks.create(destination, client, true) + return { lockId } + } catch (error) { + client.release(error instanceof Error ? error : new Error(String(error))) + throw error + } + } catch (error) { + return toErrorResponse(error, request ?? undefined) + } + } + + async #handleCommitTransaction(rawRequest: unknown): Promise { + this.#stats.commitTransaction++ + let request: CommitTransactionRequest | undefined + let context: CommitTransactionRequest | (CommitTransactionRequest & { destination?: string }) | undefined + + try { + validateLockRequestEnvelope(rawRequest, this.#config) + request = rawRequest as CommitTransactionRequest + context = request + context = this.#withLockContext(request) + + await this.#locks.commit(request.lockId) + return { committed: true } + } catch (error) { + return toErrorResponse(error, context ?? undefined) + } + } + + async #handleRollbackTransaction(rawRequest: unknown): Promise { + this.#stats.rollbackTransaction++ + let request: RollbackTransactionRequest | undefined + let context: RollbackTransactionRequest | (RollbackTransactionRequest & { destination?: string }) | undefined + + try { + validateLockRequestEnvelope(rawRequest, this.#config) + request = rawRequest as RollbackTransactionRequest + context = request + context = this.#withLockContext(request) + + await this.#locks.rollback(request.lockId) + return { rolledBack: true } + } catch (error) { + return toErrorResponse(error, context ?? undefined) + } + } + + async #handleCancel(rawRequest: unknown): Promise { + this.#stats.cancel++ + let request: CancelRequest | undefined + + try { + validateCancelRequest(rawRequest) + request = rawRequest as CancelRequest + + return this.#cancellations.cancel(request.requestId, request.lockId) + } catch (error) { + return toErrorResponse(error, request ?? undefined) + } + } + + #handleResetStats(): { reset: boolean } { + for (const key of Object.keys(this.#stats)) { + this.#stats[key] = 0 + } + + return { reset: true } + } + + #withLockContext( + request: T + ): T & { destination?: string } { + return { + ...request, + destination: this.#locks.getDestination(request.lockId), + } + } + + #assertAcceptingWork(): void { + if (this.#shuttingDown) { + throw new DatabaseWattError('SHUTDOWN', 'Database application is shutting down') + } + } + + #buildBeginStatement(request: BeginTransactionRequest): string { + const modes: string[] = [] + const isolationLevel = this.#normalizeIsolationLevel(request.isolationLevel) + + if (isolationLevel) { + modes.push(`ISOLATION LEVEL ${isolationLevel}`) + } + + if (request.readOnly) { + modes.push('READ ONLY') + } + + if (modes.length === 0) { + return 'BEGIN' + } + + return `BEGIN ${modes.join(', ')}` + } + + #normalizeIsolationLevel(isolationLevel: string | undefined): string | undefined { + switch (isolationLevel) { + case 'read committed': + return 'READ COMMITTED' + case 'repeatable read': + return 'REPEATABLE READ' + case 'serializable': + return 'SERIALIZABLE' + default: + return undefined + } + } + + async #withShutdownTimeout(promise: Promise, timeoutMs: number): Promise { + let timeout: NodeJS.Timeout | undefined + const timeoutPromise = new Promise((_, reject) => { + timeout = setTimeout(() => { + reject(new DatabaseWattError('SHUTDOWN', 'Database application shutdown timed out')) + }, timeoutMs) + timeout.unref() + }) + + try { + return await Promise.race([promise, timeoutPromise]) + } finally { + if (timeout) { + clearTimeout(timeout) + } + } + } +} + +export interface ApplicationContext { + app: Application + isBackgroundApplication: boolean + close: () => Promise +} + +export function create() { + const app = new Application() + + return { + app, + isBackgroundApplication: true, + close: app.close.bind(app), + } +} diff --git a/src/database/locks.ts b/src/database/locks.ts new file mode 100644 index 000000000..09dbd49a7 --- /dev/null +++ b/src/database/locks.ts @@ -0,0 +1,216 @@ +import { randomBytes } from 'node:crypto' +import type { PoolClient, QueryResultRow } from 'pg' +import type { DatabaseConfig } from './config.js' +import { DatabaseWattError } from './errors.js' +import { isConnectionStateError, runQuery, toQueryResponse } from './pools.js' +import type { DestinationConfig, QueryResponse } from './types.js' + +type LockRecord = { + busy: Promise + client: PoolClient + createdAt: number + destination: DestinationConfig + inTransaction: boolean + lastUsedAt: number + lockId: string + terminal: boolean +} + +export class LockRegistry { + private readonly config: DatabaseConfig + private readonly locks = new Map() + private readonly cleanupInterval: NodeJS.Timeout + + constructor(config: DatabaseConfig) { + this.config = config + this.cleanupInterval = setInterval(() => { + void this.expireLocks() + }, Math.min(config.lockIdleTimeoutMs, config.lockMaxLifetimeMs, 10_000)) + this.cleanupInterval.unref() + } + + create(destination: DestinationConfig, client: PoolClient, inTransaction = false): string { + const lockId = randomBytes(32).toString('base64url') + const now = Date.now() + this.locks.set(lockId, { + busy: Promise.resolve(), + client, + createdAt: now, + destination, + inTransaction, + lastUsedAt: now, + lockId, + terminal: false, + }) + return lockId + } + + getDestination(lockId: string): string | undefined { + return this.locks.get(lockId)?.destination.id + } + + getClient(lockId: string): PoolClient { + return this.getLock(lockId).client + } + + async query( + lockId: string, + sql: string, + values?: unknown[] + ): Promise> { + return this.withLock(lockId, async (lock) => { + const result = await runQuery(lock.client, sql, values) + return toQueryResponse(result) + }) + } + + async release(lockId: string): Promise { + await this.withLock(lockId, async (lock) => { + if (lock.inTransaction) { + throw new DatabaseWattError('PROTOCOL_ERROR', 'Cannot release a transaction lock') + } + + this.remove(lock, undefined) + }) + } + + async markTransaction(lockId: string): Promise { + await this.withLock(lockId, async (lock) => { + lock.inTransaction = true + }) + } + + async commit(lockId: string): Promise { + await this.withLock(lockId, async (lock) => { + if (!lock.inTransaction) { + throw new DatabaseWattError('PROTOCOL_ERROR', 'Lock is not in a transaction') + } + + let releaseError: Error | undefined + try { + await runQuery(lock.client, 'COMMIT') + } catch (error) { + releaseError = error instanceof Error ? error : new Error(String(error)) + throw error + } finally { + this.remove(lock, releaseError) + } + }) + } + + async rollback(lockId: string): Promise { + await this.withLock(lockId, async (lock) => { + if (!lock.inTransaction) { + this.remove(lock, undefined) + return + } + + let releaseError: Error | undefined + try { + await runQuery(lock.client, 'ROLLBACK') + } catch (error) { + releaseError = error instanceof Error ? error : new Error(String(error)) + throw error + } finally { + this.remove(lock, releaseError) + } + }) + } + + async purge(lockId: string, releaseError?: Error): Promise { + const lock = this.locks.get(lockId) + if (!lock) { + return + } + + await lock.busy.catch(() => undefined) + this.remove(lock, releaseError) + } + + async close(): Promise { + clearInterval(this.cleanupInterval) + const locks = [...this.locks.values()] + this.locks.clear() + + await Promise.allSettled( + locks.map(async (lock) => { + await lock.busy.catch(() => undefined) + if (lock.inTransaction) { + await runQuery(lock.client, 'ROLLBACK').catch(() => undefined) + } + lock.client.release() + }) + ) + } + + private async withLock(lockId: string, fn: (lock: LockRecord) => Promise): Promise { + const lock = this.getLock(lockId) + const work = lock.busy.then(async () => { + this.assertUsable(lock) + lock.lastUsedAt = Date.now() + + try { + return await fn(lock) + } catch (error) { + if (isConnectionStateError(error)) { + this.remove(lock, error instanceof Error ? error : new Error(String(error))) + } + throw error + } + }) + + lock.busy = work.catch(() => undefined) + return work + } + + private getLock(lockId: string): LockRecord { + const lock = this.locks.get(lockId) + if (!lock || lock.terminal) { + throw new DatabaseWattError('PROTOCOL_ERROR', 'Unknown lock ID') + } + return lock + } + + private assertUsable(lock: LockRecord): void { + const now = Date.now() + if (now - lock.createdAt > this.config.lockMaxLifetimeMs) { + this.remove(lock, new Error('Lock maximum lifetime exceeded')) + throw new DatabaseWattError('PROTOCOL_ERROR', 'Unknown lock ID') + } + + if (now - lock.lastUsedAt > this.config.lockIdleTimeoutMs) { + this.remove(lock, new Error('Lock idle timeout exceeded')) + throw new DatabaseWattError('PROTOCOL_ERROR', 'Unknown lock ID') + } + } + + private remove(lock: LockRecord, releaseError: Error | undefined): void { + if (lock.terminal) { + return + } + + lock.terminal = true + this.locks.delete(lock.lockId) + lock.client.release(releaseError) + } + + private async expireLocks(): Promise { + const now = Date.now() + const expired = [...this.locks.values()].filter((lock) => { + return ( + now - lock.createdAt > this.config.lockMaxLifetimeMs || + now - lock.lastUsedAt > this.config.lockIdleTimeoutMs + ) + }) + + await Promise.allSettled( + expired.map(async (lock) => { + await lock.busy.catch(() => undefined) + if (lock.inTransaction) { + await runQuery(lock.client, 'ROLLBACK').catch(() => undefined) + } + this.remove(lock, undefined) + }) + ) + } +} diff --git a/src/database/metrics.ts b/src/database/metrics.ts new file mode 100644 index 000000000..d7e33c8f9 --- /dev/null +++ b/src/database/metrics.ts @@ -0,0 +1,36 @@ +import { metrics } from '@opentelemetry/api' +import type { PoolRegistry } from './pools.js' + +let registered = false + +export function registerDatabaseWattMetrics(pools: PoolRegistry): void { + if (registered) { + return + } + + registered = true + const meter = metrics.getMeter('storage-database-watt') + const activePools = meter.createObservableGauge('database_watt_active_pools', { + description: 'Current number of active Database Watt destination pools', + }) + const totalConnections = meter.createObservableGauge('database_watt_connections', { + description: 'Current number of Database Watt PostgreSQL connections', + }) + const inUseConnections = meter.createObservableGauge('database_watt_connections_in_use', { + description: 'Current number of Database Watt PostgreSQL connections in use', + }) + const waitingRequests = meter.createObservableGauge('database_watt_waiting_requests', { + description: 'Current number of Database Watt requests waiting for PostgreSQL connections', + }) + + meter.addBatchObservableCallback( + (observer) => { + const stats = pools.getStats() + observer.observe(activePools, stats.pools) + observer.observe(totalConnections, stats.totalConnections) + observer.observe(inUseConnections, stats.inUseConnections) + observer.observe(waitingRequests, stats.waitingRequests) + }, + [activePools, totalConnections, inUseConnections, waitingRequests] + ) +} diff --git a/src/database/pg-lib-connection.d.ts b/src/database/pg-lib-connection.d.ts new file mode 100644 index 000000000..d38e683f4 --- /dev/null +++ b/src/database/pg-lib-connection.d.ts @@ -0,0 +1,11 @@ +declare module 'pg/lib/connection' { + import { EventEmitter } from 'node:events' + + export default class PgConnection extends EventEmitter { + cancel(processID: number, secretKey: number): void + connect(port: number, host: string): void + connect(path: string): void + end(): void + unref(): void + } +} diff --git a/src/database/pools.ts b/src/database/pools.ts new file mode 100644 index 000000000..ae50e4c5e --- /dev/null +++ b/src/database/pools.ts @@ -0,0 +1,225 @@ +import { Pool, type PoolClient, type QueryResult, type QueryResultRow } from 'pg' +import type { DatabaseConfig } from './config.js' +import { DatabaseWattError } from './errors.js' +import { getSslSettings } from './ssl.js' +import type { DestinationConfig, QueryResponse } from './types.js' + +type PoolEntry = { + config: DestinationConfig + lastUsedAt: number + pool: Pool +} + +export type PoolRegistryStats = { + pools: number + totalConnections: number + inUseConnections: number + waitingRequests: number +} + +export class PoolRegistry { + private readonly config: DatabaseConfig + private readonly pools = new Map() + private pendingGlobalAcquisitions = 0 + private readonly evictionInterval: NodeJS.Timeout + + constructor(config: DatabaseConfig) { + this.config = config + this.evictionInterval = setInterval(() => { + void this.evictIdlePools() + }, Math.max(config.idlePoolTimeoutMs, 1_000)) + this.evictionInterval.unref() + } + + async query( + destination: DestinationConfig, + sql: string, + values: unknown[] | undefined, + onClient?: (client: PoolClient) => void + ): Promise> { + const client = await this.acquire(destination) + let releaseError: Error | undefined + + try { + onClient?.(client) + const result = await runQuery(client, sql, values) + return toQueryResponse(result) + } catch (error) { + if (isConnectionStateError(error)) { + releaseError = error instanceof Error ? error : new Error(String(error)) + } + throw error + } finally { + client.release(releaseError) + } + } + + async acquire(destination: DestinationConfig): Promise { + const entry = this.getOrCreatePool(destination) + this.assertCanAcquire(entry) + this.pendingGlobalAcquisitions++ + + const timeout = createTimeout(this.config.acquireTimeoutMs) + try { + return await Promise.race([ + entry.pool.connect(), + timeout.promise.then(() => { + throw new DatabaseWattError('ACQUIRE_TIMEOUT', 'Timed out acquiring database connection') + }), + ]) + } finally { + timeout.clear() + this.pendingGlobalAcquisitions-- + entry.lastUsedAt = Date.now() + } + } + + getStats(): PoolRegistryStats { + let inUseConnections = 0 + let totalConnections = 0 + let waitingRequests = 0 + + for (const entry of this.pools.values()) { + inUseConnections += Math.max(entry.pool.totalCount - entry.pool.idleCount, 0) + totalConnections += entry.pool.totalCount + waitingRequests += entry.pool.waitingCount + } + + return { + inUseConnections, + pools: this.pools.size, + totalConnections, + waitingRequests, + } + } + + async close(): Promise { + clearInterval(this.evictionInterval) + const pools = [...this.pools.values()].map((entry) => entry.pool) + this.pools.clear() + await Promise.allSettled(pools.map((pool) => pool.end())) + } + + private getOrCreatePool(destination: DestinationConfig): PoolEntry { + const existing = this.pools.get(destination.id) + if (existing) { + existing.lastUsedAt = Date.now() + return existing + } + + if (this.pools.size >= this.config.maxActivePools) { + throw new DatabaseWattError('BUSY', 'Maximum active destination pools reached') + } + + const maxConnections = Math.max( + Math.min(destination.maxConnections, this.config.destinationMaxConnections), + 1 + ) + const pool = new Pool({ + application_name: this.config.applicationName, + connectionString: destination.connectionString, + connectionTimeoutMillis: this.config.connectionTimeoutMs, + idleTimeoutMillis: this.config.idlePoolTimeoutMs, + max: maxConnections, + min: 0, + ssl: getSslSettings(destination.connectionString, this.config.rootCert), + }) + + const entry = { + config: destination, + lastUsedAt: Date.now(), + pool, + } + + this.pools.set(destination.id, entry) + return entry + } + + private assertCanAcquire(entry: PoolEntry): void { + const stats = this.getStats() + + if (this.pendingGlobalAcquisitions >= this.config.globalAcquireQueueLimit) { + throw new DatabaseWattError('BUSY', 'Global acquisition queue is full') + } + + if (entry.pool.waitingCount >= this.config.destinationAcquireQueueLimit) { + throw new DatabaseWattError('BUSY', 'Destination acquisition queue is full') + } + + const targetHasIdleConnection = entry.pool.idleCount > 0 + if (!targetHasIdleConnection && stats.totalConnections >= this.config.globalMaxConnections) { + throw new DatabaseWattError('BUSY', 'Global connection budget is exhausted') + } + } + + private async evictIdlePools(): Promise { + const now = Date.now() + const toEvict: Pool[] = [] + + for (const [destination, entry] of this.pools) { + if (now - entry.lastUsedAt < this.config.idlePoolTimeoutMs) { + continue + } + + if (entry.pool.totalCount !== entry.pool.idleCount || entry.pool.waitingCount > 0) { + continue + } + + this.pools.delete(destination) + toEvict.push(entry.pool) + } + + await Promise.allSettled(toEvict.map((pool) => pool.end())) + } +} + +export async function runQuery( + client: PoolClient, + sql: string, + values?: unknown[] +): Promise> { + return client.query(sql, values) +} + +export function toQueryResponse( + result: QueryResult +): QueryResponse { + return { + rows: result.rows, + rowCount: result.rowCount || 0, + } +} + +export function isConnectionStateError(error: unknown): boolean { + if (!(error instanceof Error)) { + return false + } + + const code = (error as { code?: string }).code + if (typeof code === 'string' && code.startsWith('08')) { + return true + } + + return ( + error.message.startsWith('received invalid response:') || + error.message.startsWith('Received unexpected ') || + error.message.startsWith('Unknown authenticationOk message type') + ) +} + +function createTimeout(timeoutMs: number): { clear: () => void; promise: Promise } { + let timeout: NodeJS.Timeout | undefined + const promise = new Promise((resolve) => { + timeout = setTimeout(resolve, timeoutMs) + timeout.unref() + }) + + return { + clear: () => { + if (timeout) { + clearTimeout(timeout) + } + }, + promise, + } +} diff --git a/src/database/result-limits.ts b/src/database/result-limits.ts new file mode 100644 index 000000000..66f2c3064 --- /dev/null +++ b/src/database/result-limits.ts @@ -0,0 +1,17 @@ +import { Buffer } from 'node:buffer' +import type { DatabaseConfig } from './config.js' +import { DatabaseWattError } from './errors.js' +import type { QueryResponse } from './types.js' + +export function enforceResultLimits(response: QueryResponse, config: DatabaseConfig): QueryResponse { + if (response.rows.length > config.maxResultRows) { + throw new DatabaseWattError('RESULT_TOO_LARGE', 'Result row limit exceeded') + } + + const serializedSize = Buffer.byteLength(JSON.stringify(response)) + if (serializedSize > config.maxResultBytes) { + throw new DatabaseWattError('RESULT_TOO_LARGE', 'Result byte limit exceeded') + } + + return response +} diff --git a/src/database/ssl.ts b/src/database/ssl.ts new file mode 100644 index 000000000..810db9e4e --- /dev/null +++ b/src/database/ssl.ts @@ -0,0 +1,32 @@ +export function getSslSettings( + connectionString: string, + rootCert?: string +): { ca?: string; rejectUnauthorized?: boolean } | false | undefined { + const sslMode = getSslMode(connectionString) + + if (sslMode === 'disable') { + return false + } + + if (rootCert) { + return { + ca: rootCert, + } + } + + if (sslMode === 'require' || sslMode === 'prefer') { + return { + rejectUnauthorized: false, + } + } + + return undefined +} + +function getSslMode(connectionString: string): string | undefined { + try { + return new URL(connectionString).searchParams.get('sslmode') || undefined + } catch { + return undefined + } +} diff --git a/src/database/tests/cancellation.test.ts b/src/database/tests/cancellation.test.ts new file mode 100644 index 000000000..90d21e056 --- /dev/null +++ b/src/database/tests/cancellation.test.ts @@ -0,0 +1,74 @@ +import { describe, expect, it, vi } from 'vitest' +import { CancellationRegistry } from '../cancellation.js' + +describe('database cancellation registry', () => { + it('tracks missing and completed requests', async () => { + const registry = new CancellationRegistry() + + expect(await registry.cancel('missing')).toEqual({ cancelled: false }) + + registry.start('req-1', { cancelled: false }) + registry.finish('req-1') + + expect(await registry.cancel('req-1')).toEqual({ cancelled: false }) + }) + + it('marks an in-flight operation as cancelled', async () => { + const registry = new CancellationRegistry() + const operation = { cancelled: false, lockId: 'lock-a' } + + registry.start('req-1', operation) + + expect(await registry.cancel('req-1', 'lock-a')).toEqual({ cancelled: true }) + expect(operation.cancelled).toBe(true) + }) + + it('does not cancel operations for a different lock', async () => { + const registry = new CancellationRegistry() + const operation = { cancelled: false, lockId: 'lock-a' } + + registry.start('req-1', operation) + + expect(await registry.cancel('req-1', 'lock-b')).toEqual({ cancelled: false }) + expect(operation.cancelled).toBe(false) + }) + + it('sends PostgreSQL cancel when client backend identifiers are present', async () => { + vi.resetModules() + + const cancel = vi.fn() + const end = vi.fn() + const unref = vi.fn() + vi.doMock('pg/lib/connection', () => ({ + default: class MockPgConnection { + private callbacks = new Map void>() + cancel = cancel + end = end + unref = unref + on(event: string, callback: () => void) { + this.callbacks.set(event, callback) + } + connect() { + setImmediate(() => { + this.callbacks.get('connect')?.() + this.callbacks.get('end')?.() + }) + } + }, + })) + + const { CancellationRegistry: MockedCancellationRegistry } = await import('../cancellation.js') + const registry = new MockedCancellationRegistry() + registry.start('req-1', { cancelled: false }) + registry.setClient('req-1', { + connectionParameters: { host: 'localhost', port: 5432 }, + processID: 1, + secretKey: 2, + } as never) + + expect(await registry.cancel('req-1')).toEqual({ cancelled: true }) + expect(cancel).toHaveBeenCalledWith(1, 2) + expect(end).toHaveBeenCalled() + vi.doUnmock('pg/lib/connection') + }) +}) diff --git a/src/database/tests/errors.test.ts b/src/database/tests/errors.test.ts new file mode 100644 index 000000000..4dc72a3d5 --- /dev/null +++ b/src/database/tests/errors.test.ts @@ -0,0 +1,45 @@ +import { DatabaseError } from 'pg' +import { describe, expect, it } from 'vitest' +import { DatabaseWattError, isErrorResponse, toErrorResponse } from '../errors.js' + +describe('database error contract', () => { + it('serializes DatabaseWattError with safe context', () => { + const response = toErrorResponse(new DatabaseWattError('BUSY', 'queue full'), { + destination: 'tenant-a', + operationName: 'op', + requestId: 'req-1', + }) + + expect(response).toMatchObject({ + code: 'BUSY', + destination: 'tenant-a', + message: 'queue full', + operationName: 'op', + requestId: 'req-1', + }) + }) + + it('maps PostgreSQL errors to POSTGRES_ERROR and SQLSTATE', () => { + const error = new DatabaseError('duplicate key', 1, 'error') + error.code = '23505' + + const response = toErrorResponse(error, { lockId: 'lock-a' }) + + expect(response).toMatchObject({ + code: 'POSTGRES_ERROR', + lockId: 'lock-a', + message: 'duplicate key', + sqlState: '23505', + }) + }) + + it('maps unknown errors to MESSAGING_ERROR', () => { + const response = toErrorResponse(new Error('transport failed')) + + expect(response).toMatchObject({ + code: 'MESSAGING_ERROR', + message: 'transport failed', + }) + expect(isErrorResponse(response)).toBe(true) + }) +}) diff --git a/src/database/tests/index.test.ts b/src/database/tests/index.test.ts new file mode 100644 index 000000000..da8ae4997 --- /dev/null +++ b/src/database/tests/index.test.ts @@ -0,0 +1,304 @@ +import { setupLoopbackMessaging } from '@platformatic/runtime' +import { afterEach, describe, expect, it, vi } from 'vitest' +import type { DatabaseErrorResponse } from '../errors.js' +import type { ApplicationContext } from '../index.js' + +type Handler = (data: unknown) => Promise + +type MockClient = { + queries: Array<{ sql: string; values?: unknown[] }> + query: ReturnType + release: ReturnType +} + +type MockedEnvironment = { + app: ApplicationContext, + messaging: ReturnType + clients: MockClient[] + pools: Array<{ config: Record; ended: boolean; queries: Array<{ sql: string; values?: unknown[] }> }> +} + +function createMockClient(rows: unknown[]): MockClient { + const client: MockClient = { + queries: [], + query: vi.fn(async (sql: string, values?: unknown[]) => { + client.queries.push({ sql, values }) + return { rowCount: rows.length, rows } + }), + release: vi.fn(), + } + + return client +} + +async function loadApp(options: { + env?: Record + queryRows?: unknown[] + tenantRows?: unknown[] +} = {}): Promise { + vi.resetModules() + + const handlers = new Map() + const clients: MockClient[] = [] + const pools: MockedEnvironment['pools'] = [] + const queryRows = options.queryRows || [{ ok: true }] + const tenantRows = options.tenantRows || [] + + process.env = { + ...originalEnv, + DATABASE_URL: 'postgres://single-tenant', + ...options.env, + } + + vi.doMock('pg', () => { + class MockDatabaseError extends Error { + code?: string + constructor(message: string) { + super(message) + } + } + + class MockPool { + totalCount = 0 + idleCount = 0 + waitingCount = 0 + ended = false + queries: Array<{ sql: string; values?: unknown[] }> = [] + config: Record + + constructor(config: Record) { + this.config = config + pools.push(this) + } + + async query(sql: string, values?: unknown[]) { + this.queries.push({ sql, values }) + return { rowCount: tenantRows.length, rows: tenantRows } + } + + async connect() { + this.totalCount++ + const client = createMockClient(queryRows) + clients.push(client) + return client + } + + async end() { + this.ended = true + } + } + + return { + DatabaseError: MockDatabaseError, + Pool: MockPool, + default: { types: { setTypeParser: vi.fn() } }, + } + }) + + vi.doMock('pg/lib/connection', () => ({ + default: class MockPgConnection {}, + })) + + // We need dynamic import due to the mocking of PostgreSQL modules above + const {create} = await import('../index.js') + + const messaging = setupLoopbackMessaging('db') + const app = create() + return { app, messaging, clients, pools } +} + +const originalEnv = { ...process.env } + +afterEach(async () => { + vi.doUnmock('pg') + vi.doUnmock('pg/lib/connection') + vi.resetModules() + process.env = { ...originalEnv } +}) + +describe('database Watt application messaging handlers', () => { + it('registers prefixed handlers and exposes no server', async () => { + const { app } = await loadApp() + + expect(app.isBackgroundApplication).toBe(true) + }) + + it('executes stateless queries against the single-tenant destination', async () => { + const { messaging, clients } = await loadApp() + + const response = await messaging.send('foo', 'database.query', { + destination: 'default', + requestId: 'req-1', + sql: 'SELECT 1', + values: [1], + }) + + expect(response).toEqual({ rowCount: 1, rows: [{ ok: true }] }) + expect(clients[0].query).toHaveBeenCalledWith('SELECT 1', [1]) + expect(clients[0].release).toHaveBeenCalledWith(undefined) + }) + + it('returns validation errors from malformed requests', async () => { + const { messaging } = await loadApp() + + const response = (await messaging.send('database', 'database.query', { + destination: '', + sql: 'SELECT 1', + })) as DatabaseErrorResponse + + expect(response).toMatchObject({ + code: 'PROTOCOL_ERROR', + message: 'destination must be a non-empty string', + }) + }) + + it('enforces result limits in handlers', async () => { + const { messaging } = await loadApp({ + env: { DATABASE_WATT_MAX_RESULT_ROWS: '1' }, + queryRows: [{ id: 1 }, { id: 2 }], + }) + + const response = (await messaging.send('database', 'database.query', { + destination: 'default', + sql: 'SELECT 1', + })) as DatabaseErrorResponse + + expect(response).toMatchObject({ + code: 'RESULT_TOO_LARGE', + message: 'Result row limit exceeded', + }) + expect(response).not.toHaveProperty('rows') + }) + + it('acquires and releases pinned connections', async () => { + const { clients, messaging } = await loadApp() + + const acquire = (await messaging.send('database', 'database.acquire', { + destination: 'default', + })) as { lockId: string } + + expect(acquire.lockId).toBeTruthy() + + const release = await messaging.send('database', 'database.release', { lockId: acquire.lockId }) + + expect(release).toEqual({ released: true }) + expect(clients[0].release).toHaveBeenCalledWith(undefined) + }) + + it('runs transaction lifecycle on one pinned connection', async () => { + const { clients, messaging } = await loadApp() + + const begin = (await messaging.send('database', 'database.beginTransaction', { + destination: 'default', + isolationLevel: 'serializable', + readOnly: true, + })) as { lockId: string } + + expect(begin.lockId).toBeTruthy() + + await messaging.send('database', 'database.lockedQuery', { + lockId: begin.lockId, + sql: 'SELECT 1', + }) + const commit = await messaging.send('database', 'database.commitTransaction', { lockId: begin.lockId }) + + expect(commit).toEqual({ committed: true }) + expect(clients[0].queries.map((query) => query.sql)).toEqual([ + 'BEGIN ISOLATION LEVEL SERIALIZABLE, READ ONLY', + `SELECT set_config('statement_timeout', $1, true)`, + 'SELECT 1', + 'COMMIT', + ]) + expect(clients[0].release).toHaveBeenCalledWith(undefined) + }) + + it('resolves multitenant destinations through the master pool', async () => { + const { clients, messaging, pools } = await loadApp({ + env: { DATABASE_MULTITENANT_URL: 'postgres://master', MULTI_TENANT: 'true' }, + tenantRows: [{ database_url: 'postgres://tenant-db', max_connections: 4 }], + }) + + const response = await messaging.send('database', 'database.query', { + destination: 'tenant-a', + sql: 'SELECT 1', + }) + + expect(response).toEqual({ rowCount: 1, rows: [{ ok: true }] }) + expect(pools[0].queries[0]).toMatchObject({ + values: ['tenant-a'], + }) + expect(clients[0].query).toHaveBeenCalledWith('SELECT 1', undefined) + }) + + it('resolves the reserved master destination directly to the master database', async () => { + const { clients, messaging, pools } = await loadApp({ + env: { DATABASE_MULTITENANT_URL: 'postgres://master', MULTI_TENANT: 'true' }, + }) + + const response = await messaging.send('database', 'database.query', { + destination: 'master', + sql: 'SELECT 1', + }) + + expect(response).toEqual({ rowCount: 1, rows: [{ ok: true }] }) + expect(pools[0].config).toMatchObject({ connectionString: 'postgres://master' }) + expect(pools[0].queries).toHaveLength(0) + expect(clients[0].query).toHaveBeenCalledWith('SELECT 1', undefined) + }) + + it('returns DESTINATION_UNKNOWN for the master destination without master config', async () => { + const { messaging } = await loadApp({ + env: { DATABASE_MULTITENANT_URL: '', MULTI_TENANT: 'true' }, + }) + + const response = (await messaging.send('database', 'database.query', { + destination: 'master', + sql: 'SELECT 1', + })) as DatabaseErrorResponse + + expect(response).toMatchObject({ + code: 'DESTINATION_UNKNOWN', + destination: 'master', + }) + }) + + it('returns DESTINATION_UNKNOWN for missing tenants', async () => { + const { messaging } = await loadApp({ + env: { DATABASE_MULTITENANT_URL: 'postgres://master', MULTI_TENANT: 'true' }, + tenantRows: [], + }) + + const response = (await messaging.send('database', 'database.query', { + destination: 'missing', + sql: 'SELECT 1', + })) as DatabaseErrorResponse + + expect(response).toMatchObject({ + code: 'DESTINATION_UNKNOWN', + destination: 'missing', + }) + }) + + it('closes pools and rejects new work after shutdown starts', async () => { + const { app, messaging, pools } = await loadApp() + + await messaging.send('database', 'database.query', { + destination: 'default', + sql: 'SELECT 1', + }) + await app.close() + + const response = (await messaging.send('database', 'database.query', { + destination: 'default', + sql: 'SELECT 1', + })) as DatabaseErrorResponse + + expect(pools[0].ended).toBe(true) + expect(response).toMatchObject({ + code: 'SHUTDOWN', + message: 'Database application is shutting down', + }) + }) +}) + + diff --git a/src/database/tests/locks.test.ts b/src/database/tests/locks.test.ts new file mode 100644 index 000000000..4f9be3a6c --- /dev/null +++ b/src/database/tests/locks.test.ts @@ -0,0 +1,121 @@ +import { describe, expect, it, vi } from 'vitest' +import { readConfig } from '../config.js' +import { DatabaseWattError } from '../errors.js' +import { LockRegistry } from '../locks.js' +import type { DestinationConfig } from '../types.js' + +type FakeClient = { + query: ReturnType + release: ReturnType +} + +function createDestination(): DestinationConfig { + return { + connectionString: 'postgres://example', + id: 'tenant-a', + isExternalPool: false, + maxConnections: 10, + } +} + +function createClient(): FakeClient { + return { + query: vi.fn().mockResolvedValue({ rowCount: 1, rows: [{ ok: true }] }), + release: vi.fn(), + } +} + +describe('database lock registry', () => { + it('runs locked queries on the pinned client', async () => { + const locks = new LockRegistry(readConfig()) + const client = createClient() + const lockId = locks.create(createDestination(), client as never) + + const result = await locks.query(lockId, 'SELECT 1', [1]) + + expect(result).toEqual({ rowCount: 1, rows: [{ ok: true }] }) + expect(client.query).toHaveBeenCalledWith('SELECT 1', [1]) + expect(client.release).not.toHaveBeenCalled() + + await locks.release(lockId) + expect(client.release).toHaveBeenCalledTimes(1) + await locks.close() + }) + + it('rejects reuse after release', async () => { + const locks = new LockRegistry(readConfig()) + const client = createClient() + const lockId = locks.create(createDestination(), client as never) + + await locks.release(lockId) + + await expect(locks.query(lockId, 'SELECT 1')).rejects.toMatchObject({ + code: 'PROTOCOL_ERROR', + message: 'Unknown lock ID', + }) + await locks.close() + }) + + it('does not release transaction locks through release()', async () => { + const locks = new LockRegistry(readConfig()) + const client = createClient() + const lockId = locks.create(createDestination(), client as never, true) + + await expect(locks.release(lockId)).rejects.toBeInstanceOf(DatabaseWattError) + expect(client.release).not.toHaveBeenCalled() + + await locks.rollback(lockId) + expect(client.query).toHaveBeenCalledWith('ROLLBACK', undefined) + expect(client.release).toHaveBeenCalledTimes(1) + await locks.close() + }) + + it('commits transactions and removes terminal locks', async () => { + const locks = new LockRegistry(readConfig()) + const client = createClient() + const lockId = locks.create(createDestination(), client as never, true) + + await locks.commit(lockId) + + expect(client.query).toHaveBeenCalledWith('COMMIT', undefined) + expect(client.release).toHaveBeenCalledTimes(1) + await expect(locks.rollback(lockId)).rejects.toMatchObject({ code: 'PROTOCOL_ERROR' }) + await locks.close() + }) + + it('serializes lock-bound work for the same lock', async () => { + const locks = new LockRegistry(readConfig()) + const client = createClient() + const order: string[] = [] + let releaseFirstQuery!: () => void + + client.query.mockImplementationOnce( + () => + new Promise((resolve) => { + order.push('first-start') + releaseFirstQuery = () => { + order.push('first-end') + resolve({ rowCount: 1, rows: [] }) + } + }) + ) + client.query.mockImplementationOnce(async () => { + order.push('second-start') + return { rowCount: 1, rows: [] } + }) + + const lockId = locks.create(createDestination(), client as never) + const first = locks.query(lockId, 'SELECT 1') + const second = locks.query(lockId, 'SELECT 2') + + await new Promise((resolve) => setImmediate(resolve)) + expect(order).toEqual(['first-start']) + + releaseFirstQuery() + await Promise.all([first, second]) + + expect(order).toEqual(['first-start', 'first-end', 'second-start']) + await locks.release(lockId) + await locks.close() + }) +}) diff --git a/src/database/tests/result-limits.test.ts b/src/database/tests/result-limits.test.ts new file mode 100644 index 000000000..c1cbe2d41 --- /dev/null +++ b/src/database/tests/result-limits.test.ts @@ -0,0 +1,29 @@ +import { describe, expect, it } from 'vitest' +import { readConfig } from '../config.js' +import { DatabaseWattError } from '../errors.js' +import { enforceResultLimits } from '../result-limits.js' + +describe('database result limits', () => { + it('returns bounded results unchanged', () => { + const config = readConfig({ DATABASE_WATT_MAX_RESULT_ROWS: '2', DATABASE_WATT_MAX_RESULT_BYTES: '1000' }) + const result = { rowCount: 1, rows: [{ id: 1 }] } + + expect(enforceResultLimits(result, config)).toBe(result) + }) + + it('rejects row limits without returning partial rows', () => { + const config = readConfig({ DATABASE_WATT_MAX_RESULT_ROWS: '1', DATABASE_WATT_MAX_RESULT_BYTES: '1000' }) + + expect(() => enforceResultLimits({ rowCount: 2, rows: [{ id: 1 }, { id: 2 }] }, config)).toThrow( + DatabaseWattError + ) + }) + + it('rejects byte limits', () => { + const config = readConfig({ DATABASE_WATT_MAX_RESULT_ROWS: '10', DATABASE_WATT_MAX_RESULT_BYTES: '20' }) + + expect(() => enforceResultLimits({ rowCount: 1, rows: [{ value: 'x'.repeat(100) }] }, config)).toThrow( + /byte limit/ + ) + }) +}) diff --git a/src/database/tests/validation.test.ts b/src/database/tests/validation.test.ts new file mode 100644 index 000000000..dca67fab9 --- /dev/null +++ b/src/database/tests/validation.test.ts @@ -0,0 +1,76 @@ +import { describe, expect, it } from 'vitest' +import { readConfig } from '../config.js' +import { DatabaseWattError } from '../errors.js' +import { + validateCancelRequest, + validateLockRequestEnvelope, + validateNonLockRequestEnvelope, + validateQueryEnvelope, +} from '../validation.js' + +describe('database request validation', () => { + const config = readConfig({ + DATABASE_WATT_MAX_OPERATION_NAME_LENGTH: '8', + DATABASE_WATT_MAX_PARAMETER_COUNT: '2', + DATABASE_WATT_MAX_REQUEST_ID_LENGTH: '8', + DATABASE_WATT_MAX_SERIALIZED_REQUEST_BYTES: '200', + DATABASE_WATT_MAX_SQL_BYTES: '10', + }) + + it('accepts valid stateless query envelopes', () => { + const request = { + destination: 'tenant-a', + operationName: 'select', + requestId: 'req-1', + sql: 'SELECT 1', + values: [1], + } + + expect(() => validateNonLockRequestEnvelope(request, config)).not.toThrow() + expect(() => validateQueryEnvelope(request, config)).not.toThrow() + }) + + it('rejects missing destinations before query execution', () => { + expect(() => validateNonLockRequestEnvelope({ sql: 'SELECT 1' }, config)).toThrow( + DatabaseWattError + ) + }) + + it('rejects missing lock identifiers for lock-bound requests', () => { + expect(() => validateLockRequestEnvelope({ sql: 'SELECT 1' }, config)).toThrow( + /lockId/ + ) + }) + + it('rejects invalid SQL and parameter payloads', () => { + expect(() => validateQueryEnvelope({ sql: 1 }, config)).toThrow(/sql/) + expect(() => validateQueryEnvelope({ sql: 'SELECT 1', values: 'bad' }, config)).toThrow( + /values/ + ) + expect(() => validateQueryEnvelope({ sql: 'SELECT 1', values: [1, 2, 3] }, config)).toThrow( + /maxParameterCount/ + ) + expect(() => validateQueryEnvelope({ sql: 'SELECT 1234567890' }, config)).toThrow( + /maxSqlBytes/ + ) + }) + + it('bounds metadata and serialized request size', () => { + expect(() => + validateNonLockRequestEnvelope({ destination: 'a', requestId: 'too-long-request-id' }, config) + ).toThrow(/requestId/) + + expect(() => + validateNonLockRequestEnvelope({ destination: 'a', operationName: 'too-long-operation' }, config) + ).toThrow(/operationName/) + + expect(() => + validateNonLockRequestEnvelope({ destination: 'a', padding: 'x'.repeat(500) }, config) + ).toThrow(/maxSerializedRequestBytes/) + }) + + it('validates cancellation requests', () => { + expect(() => validateCancelRequest({ requestId: 'req-1' })).not.toThrow() + expect(() => validateCancelRequest({})).toThrow(/requestId/) + }) +}) diff --git a/src/database/types.ts b/src/database/types.ts new file mode 100644 index 000000000..347ee896d --- /dev/null +++ b/src/database/types.ts @@ -0,0 +1,60 @@ +export type WireRequestMeta = { + requestId?: string + operationName?: string +} + +export type QueryRequest = WireRequestMeta & { + destination: string + sql: string + values?: unknown[] +} + +export type AcquireConnectionRequest = WireRequestMeta & { + destination: string +} + +export type AcquireConnectionResponse = { + lockId: string +} + +export type LockedQueryRequest = WireRequestMeta & { + lockId: string + sql: string + values?: unknown[] +} + +export type ReleaseConnectionRequest = WireRequestMeta & { + lockId: string +} + +export type BeginTransactionRequest = WireRequestMeta & { + destination: string + isolationLevel?: 'read committed' | 'repeatable read' | 'serializable' + readOnly?: boolean +} + +export type CommitTransactionRequest = WireRequestMeta & { + lockId: string +} + +export type RollbackTransactionRequest = WireRequestMeta & { + lockId: string +} + +export type CancelRequest = { + requestId: string + lockId?: string +} + +export type QueryResponse = { + rows: T[] + rowCount: number +} + +export type DestinationConfig = { + connectionString: string + id: string + isExternalPool: boolean + maxConnections: number + poolMode?: string | null +} diff --git a/src/database/validation.ts b/src/database/validation.ts new file mode 100644 index 000000000..dc16389b1 --- /dev/null +++ b/src/database/validation.ts @@ -0,0 +1,85 @@ +import { Buffer } from 'node:buffer' +import type { DatabaseConfig } from './config.js' +import { DatabaseWattError } from './errors.js' + +export function validateNonLockRequestEnvelope( + request: unknown, + config: DatabaseConfig +): void { + validateBaseEnvelope(request, config) + const destination = (request as { destination?: unknown }).destination + if (typeof destination !== 'string' || destination.length === 0) { + throw new DatabaseWattError('PROTOCOL_ERROR', 'destination must be a non-empty string') + } +} + +export function validateLockRequestEnvelope( + request: unknown, + config: DatabaseConfig +): void { + validateBaseEnvelope(request, config) + const lockId = (request as { lockId?: unknown }).lockId + if (typeof lockId !== 'string' || lockId.length === 0) { + throw new DatabaseWattError('PROTOCOL_ERROR', 'lockId must be a non-empty string') + } +} + +export function validateQueryEnvelope( + request: unknown, + config: DatabaseConfig +): void { + const sql = (request as { sql?: unknown }).sql + const values = (request as { values?: unknown }).values + + if (typeof sql !== 'string') { + throw new DatabaseWattError('PROTOCOL_ERROR', 'sql must be a string') + } + + if (Buffer.byteLength(sql) > config.maxSqlBytes) { + throw new DatabaseWattError('PROTOCOL_ERROR', 'sql exceeds maxSqlBytes') + } + + if (values !== undefined && !Array.isArray(values)) { + throw new DatabaseWattError('PROTOCOL_ERROR', 'values must be an array when present') + } + + if (Array.isArray(values) && values.length > config.maxParameterCount) { + throw new DatabaseWattError('PROTOCOL_ERROR', 'values exceeds maxParameterCount') + } +} + +export function validateCancelRequest(request: unknown): void { + if (!request || typeof request !== 'object') { + throw new DatabaseWattError('PROTOCOL_ERROR', 'request must be an object') + } + + const requestId = (request as { requestId?: unknown }).requestId + if (typeof requestId !== 'string' || requestId.length === 0) { + throw new DatabaseWattError('PROTOCOL_ERROR', 'requestId must be a non-empty string') + } +} + +function validateBaseEnvelope(request: unknown, config: DatabaseConfig): void { + if (!request || typeof request !== 'object') { + throw new DatabaseWattError('PROTOCOL_ERROR', 'request must be an object') + } + + const serializedSize = Buffer.byteLength(JSON.stringify(request)) + if (serializedSize > config.maxSerializedRequestBytes) { + throw new DatabaseWattError('PROTOCOL_ERROR', 'request exceeds maxSerializedRequestBytes') + } + + const requestId = (request as { requestId?: unknown }).requestId + if (requestId !== undefined) { + if (typeof requestId !== 'string' || requestId.length > config.maxRequestIdLength) { + throw new DatabaseWattError('PROTOCOL_ERROR', 'requestId is invalid') + } + } + + const operationName = (request as { operationName?: unknown }).operationName + if (operationName !== undefined) { + if (typeof operationName !== 'string' || operationName.length > config.maxOperationNameLength) { + throw new DatabaseWattError('PROTOCOL_ERROR', 'operationName is invalid') + } + } +} diff --git a/src/internal/database/client.test.ts b/src/internal/database/client.test.ts new file mode 100644 index 000000000..4a2af3ed8 --- /dev/null +++ b/src/internal/database/client.test.ts @@ -0,0 +1,141 @@ +import { removeGlobals, updateGlobals } from '@platformatic/globals' +import { afterEach, describe, expect, it, vi } from 'vitest' + +type LoadClientOptions = { + isMultitenant?: boolean + hasWattMessaging?: boolean + disableHostCheck?: boolean +} + +afterEach(() => { + vi.doUnmock('@internal/cluster') + vi.doUnmock('@internal/errors') + vi.doUnmock('../../config') + vi.doUnmock('./pg-connection') + vi.doUnmock('./tenant') + vi.doUnmock('./watt-connection') + vi.resetModules() + removeGlobals(['messaging']) +}) + +describe('database connection client', () => { + it('uses Database Watt when messaging is available', async () => { + const { client, getTenantConfig, getWattPostgresConnection, wattConnection } = await loadClient({ + hasWattMessaging: true, + }) + + const connection = await client.getPostgresConnection(createConnectionOptions()) + + expect(connection).toBe(wattConnection) + expect(getTenantConfig).not.toHaveBeenCalled() + expect(getWattPostgresConnection).toHaveBeenCalledWith( + expect.objectContaining({ + dbUrl: '', + isExternalPool: false, + isSingleUse: false, + maxConnections: 20, + tenantId: 'tenant-a', + }) + ) + }) + + it('falls back to direct PostgreSQL when Watt messaging is unavailable', async () => { + const { client, getTenantConfig, pgConnection, pgCreate } = await loadClient({ + hasWattMessaging: false, + }) + + const connection = await client.getPostgresConnection(createConnectionOptions()) + + expect(connection).toBe(pgConnection) + expect(getTenantConfig).toHaveBeenCalledWith('tenant-a') + expect(pgCreate).toHaveBeenCalledWith( + expect.objectContaining({ + clusterSize: 3, + dbUrl: 'postgres://tenant-db', + maxConnections: 7, + }) + ) + }) + + it('validates multitenant forwarded host before routing to Database Watt', async () => { + const { client, getWattPostgresConnection } = await loadClient({ + hasWattMessaging: true, + isMultitenant: true, + }) + + await expect( + client.getPostgresConnection( + createConnectionOptions({ host: 'evil.example.test', disableHostCheck: false }) + ) + ).rejects.toThrow('X-Forwarded-Host header does not match regular expression') + + expect(getWattPostgresConnection).not.toHaveBeenCalled() + }) +}) + +async function loadClient(options: LoadClientOptions = {}) { + vi.resetModules() + + const getTenantConfig = vi.fn(async () => ({ + databasePoolMode: 'transaction', + databasePoolUrl: undefined, + databaseUrl: 'postgres://tenant-db', + maxConnections: 7, + })) + const pgConnection = { kind: 'pg-connection' } + const wattConnection = { kind: 'watt-connection' } + const pgCreate = vi.fn(async () => pgConnection) + const getWattPostgresConnection = vi.fn(async () => wattConnection) + + vi.doMock('@internal/cluster', () => ({ Cluster: { size: 3 } })) + vi.doMock('@internal/errors', () => ({ + ERRORS: { + InvalidTenantId: () => new Error('Invalid tenant id'), + InvalidXForwardedHeader: (message: string) => new Error(message), + }, + })) + vi.doMock('../../config', () => ({ + getConfig: () => ({ + databaseMaxConnections: 20, + databasePoolMode: 'transaction', + databasePoolURL: undefined, + databaseURL: 'postgres://default-db', + isMultitenant: options.isMultitenant ?? true, + requestXForwardedHostRegExp: '^tenant-[a-z]+\\.example\\.test$', + }), + normalizeDatabasePoolMode: (value: string | undefined) => value, + })) + vi.doMock('./pg-connection', () => ({ + PgTenantConnection: { create: pgCreate }, + })) + vi.doMock('./tenant', () => ({ getTenantConfig })) + vi.doMock('./watt-connection', () => ({ + getWattPostgresConnection, + })) + + if(options.hasWattMessaging) { + updateGlobals({ messaging: {} as unknown as any }) + } else { + removeGlobals(['messaging']) + } + + const client = await import('./client') + return { client, getTenantConfig, getWattPostgresConnection, pgConnection, pgCreate, wattConnection } +} + +function createConnectionOptions(overrides: Partial[0]> = {}) { + return { + disableHostCheck: true, + host: 'tenant-a.example.test', + superUser: { + jwt: 'service-jwt', + payload: { role: 'service_role' }, + }, + tenantId: 'tenant-a', + user: { + jwt: 'user-jwt', + payload: { role: 'authenticated' }, + }, + ...overrides, + } +} diff --git a/src/internal/database/client.ts b/src/internal/database/client.ts index 47e06057d..6b89c0cd0 100644 --- a/src/internal/database/client.ts +++ b/src/internal/database/client.ts @@ -1,9 +1,11 @@ import { Cluster } from '@internal/cluster' import { ERRORS } from '@internal/errors' +import { hasField } from '@platformatic/globals' import { getConfig } from '../../config' import { PgTenantConnection } from './pg-connection' import { User } from './pool' import { getTenantConfig } from './tenant' +import { getWattPostgresConnection } from './watt-connection' interface ConnectionOptions { host: string @@ -31,7 +33,54 @@ export async function getPgPostgresConnection( }) } -export const getPostgresConnection = getPgPostgresConnection +function validateConnectionOptions(options: ConnectionOptions): void { + const { isMultitenant, requestXForwardedHostRegExp } = getConfig() + + if (!isMultitenant) { + return + } + + if (!options.tenantId) { + throw ERRORS.InvalidTenantId() + } + + if (!requestXForwardedHostRegExp || options.disableHostCheck) { + return + } + + const xForwardedHost = options.host + + if (typeof xForwardedHost !== 'string') { + throw ERRORS.InvalidXForwardedHeader('X-Forwarded-Host header is not a string') + } + + if (!new RegExp(requestXForwardedHostRegExp).test(xForwardedHost)) { + throw ERRORS.InvalidXForwardedHeader( + 'X-Forwarded-Host header does not match regular expression' + ) + } +} + +export async function getPostgresConnection( + options: ConnectionOptions +): Promise { + if (!hasField('messaging')) { + return getPgPostgresConnection(options) + } + + validateConnectionOptions(options) + const { databaseMaxConnections } = getConfig() + + return getWattPostgresConnection({ + ...options, + dbUrl: '', + isExternalPool: false, + isSingleUse: false, + maxConnections: options.maxConnections ?? databaseMaxConnections, + }) +} + + async function getDbSettings( tenantId: string, diff --git a/src/internal/database/migrations/migrate.ts b/src/internal/database/migrations/migrate.ts index 2ae3dc0dc..9c38a47d1 100644 --- a/src/internal/database/migrations/migrate.ts +++ b/src/internal/database/migrations/migrate.ts @@ -1,5 +1,6 @@ import { ERRORS } from '@internal/errors' import { ResetMigrationsOnTenant, RunMigrationsOnTenants } from '@storage/events' +// Database migrations intentionally keep direct pg access outside Database Watt for now. import { Client, ClientConfig } from 'pg' import { MigrationError } from 'postgres-migrations' import { runMigration } from 'postgres-migrations/dist/run-migration' diff --git a/src/internal/database/multitenant-pg.test.ts b/src/internal/database/multitenant-pg.test.ts index 838932a18..3c66bdd72 100644 --- a/src/internal/database/multitenant-pg.test.ts +++ b/src/internal/database/multitenant-pg.test.ts @@ -1,5 +1,5 @@ import { EventEmitter } from 'events' -import { vi } from 'vitest' +import { afterEach, describe, it, vi } from 'vitest' type MultitenantPgModule = typeof import('./multitenant-pg') type MockPgPoolOptions = { @@ -17,14 +17,30 @@ type MockPgPool = { connect: () => Promise end: () => Promise } +type MockWattQuery = { + destination: string + statement: unknown +} let createdPools: MockPgPool[] = [] +let wattQueries: MockWattQuery[] = [] +const originalEnv = { ...process.env } async function loadMultitenantPgModule( - configOverrides: Record = {} + configOverrides: Record = {}, + options: { hasWattMessaging?: boolean } = {} ): Promise { vi.resetModules() + process.env = { ...originalEnv, MULTI_TENANT: 'true' } mockPgModule() + mockWattConnectionModule() + const globals = await import('@platformatic/globals') + + if (options.hasWattMessaging) { + globals.updateGlobals({ messaging: {} as unknown as never }) + } else { + globals.removeGlobals(['messaging']) + } const configModule = await import('../../config') configModule.getConfig({ reload: true }) @@ -46,7 +62,9 @@ describe('multitenant pg pool', () => { await loadedModule?.closeMultitenantPg() loadedModule = undefined vi.doUnmock('pg') + vi.doUnmock('./watt-connection') vi.resetModules() + process.env = { ...originalEnv } }) it('does not pass DATABASE_SSL_ROOT_CERT into the shared multitenant pool config', async () => { @@ -195,6 +213,36 @@ describe('multitenant pg pool', () => { expect('getMultitenantPgPool' in loadedModule).toBe(false) expect('getMultitenantPgPoolConfig' in loadedModule).toBe(false) }) + + it('uses Database Watt for master queries when messaging is available', async () => { + loadedModule = await loadMultitenantPgModule({}, { hasWattMessaging: true }) + + await runQuery(loadedModule) + + expect(createdPools).toHaveLength(0) + expect(wattQueries).toEqual([ + { + destination: 'master', + statement: 'select 1', + }, + ]) + }) + + it('uses Database Watt for master transactions when messaging is available', async () => { + loadedModule = await loadMultitenantPgModule({}, { hasWattMessaging: true }) + + const tx = await loadedModule.multitenantPgExecutor.beginTransaction() + await tx.query('select 1') + await tx.commit() + + expect(createdPools).toHaveLength(0) + expect(wattQueries).toEqual([ + { + destination: 'master', + statement: 'select 1', + }, + ]) + }) }) async function runQuery(module: MultitenantPgModule): Promise { @@ -249,6 +297,37 @@ function mockPgModule(): void { }) } +function mockWattConnectionModule(): void { + wattQueries = [] + + vi.doMock('./watt-connection', () => { + class MockDatabaseWattPgExecutor { + constructor(private readonly destination: string) {} + + async query(statement: unknown) { + wattQueries.push({ destination: this.destination, statement }) + return { rowCount: 0, rows: [] } + } + + async beginTransaction() { + return { + commit: vi.fn(async () => undefined), + isCompleted: vi.fn(() => false), + query: vi.fn(async (statement: unknown) => { + wattQueries.push({ destination: this.destination, statement }) + return { rowCount: 0, rows: [] } + }), + rollback: vi.fn(async () => undefined), + } + } + } + + return { + DatabaseWattPgExecutor: MockDatabaseWattPgExecutor, + } + }) +} + function createMockPgClient(): MockPgClient { return Object.assign(new EventEmitter(), { query: vi.fn(async () => ({ rows: [] })), diff --git a/src/internal/database/multitenant-pg.ts b/src/internal/database/multitenant-pg.ts index 439a98f97..7a4ca4974 100644 --- a/src/internal/database/multitenant-pg.ts +++ b/src/internal/database/multitenant-pg.ts @@ -1,7 +1,9 @@ import { logger, logSchema } from '@internal/monitoring' +import { hasField } from '@platformatic/globals' import { Pool, PoolConfig } from 'pg' import { getConfig } from '../../config' import { attachPgPoolErrorHandler, PgPoolExecutor, PgTransactionalExecutor } from './pg-connection' +import { DatabaseWattPgExecutor } from './watt-connection' function buildMultitenantPgPoolConfig(config: ReturnType): PoolConfig { const { @@ -148,13 +150,16 @@ function getPoolConfigSignature(config: PoolConfig): string { } const multitenantPgPoolOwner = new MultitenantPgPoolOwner() +const multitenantWattExecutor = new DatabaseWattPgExecutor('master', () => 'multitenant-pg') export const multitenantPgExecutor: PgTransactionalExecutor = { async query(statement, options) { - return multitenantPgPoolOwner.getExecutor().query(statement, options) + const executor = hasField('messaging') ? multitenantWattExecutor : multitenantPgPoolOwner.getExecutor() + return executor.query(statement, options) }, async beginTransaction(options) { - return multitenantPgPoolOwner.getExecutor().beginTransaction(options) + const executor = hasField('messaging') ? multitenantWattExecutor : multitenantPgPoolOwner.getExecutor() + return executor.beginTransaction(options) }, } diff --git a/src/internal/database/pg-connection.ts b/src/internal/database/pg-connection.ts index b5ad8a170..8188ee075 100644 --- a/src/internal/database/pg-connection.ts +++ b/src/internal/database/pg-connection.ts @@ -54,6 +54,23 @@ interface PgPoolErrorContext { project?: string } +export interface PgTransactionLike extends PgExecutor { + isCompleted(): boolean + commit(): Promise + rollback(): Promise +} + +export interface PgTenantConnectionLike extends PgExecutor { + readonly role: string + dispose(): Promise + setAbortSignal(signal: AbortSignal): void + getAbortSignal(): AbortSignal | undefined + beginTransaction(options?: TransactionOptions): Promise + asSuperUser(): PgTenantConnectionLike + transaction(opts?: TransactionOptions): Promise + setScope(tnx: PgExecutor): Promise +} + type PgClientWithCancel = PoolClient & { processID?: number secretKey?: number @@ -414,7 +431,7 @@ export class PgPoolExecutor implements PgTransactionalExecutor { } } -export class PgTransaction implements PgExecutor { +export class PgTransaction implements PgTransactionLike { private completed = false constructor( @@ -501,7 +518,7 @@ export class PgTransaction implements PgExecutor { } } -export class PgTenantConnection { +export class PgTenantConnection implements PgTenantConnectionLike { static poolManager = new PgPoolManager() public readonly role: string private abortSignal?: AbortSignal diff --git a/src/internal/database/watt-connection.test.ts b/src/internal/database/watt-connection.test.ts new file mode 100644 index 000000000..3b60e4fa1 --- /dev/null +++ b/src/internal/database/watt-connection.test.ts @@ -0,0 +1,218 @@ +import { removeGlobals, updateGlobals } from '@platformatic/globals' +import { describe, expect, it } from 'vitest' +import type { TenantConnectionOptions } from './pool' +import { + DatabaseWattPgExecutor, + getWattPostgresConnection, +} from './watt-connection' + +type SentWattMessage = { + application: string + data: Record + message: string +} + +function installWattMessagingMock( + responses: Record = {} +): { sent: SentWattMessage[] } { + const sent: SentWattMessage[] = [] + + updateGlobals({ + messaging: { + send: vi.fn(async (application: string, message: string, data: Record) => { + sent.push({ application, data, message }) + const response = responses[message] + return response instanceof Promise ? response : response + }), + } as unknown as any + }) + + return { sent } +} + +afterEach(() => { + removeGlobals(['messaging']) +}) + +describe('Watt PostgreSQL connection adapter', () => { + it('sends stateless queries through Database Watt messaging', async () => { + const { sent } = installWattMessagingMock({ + 'database.query': { rowCount: 1, rows: [{ id: 1 }] }, + }) + const connection = await getWattPostgresConnection(createConnectionOptions()) + + const result = await connection.query<{ id: number }>({ text: 'SELECT $1::int as id', values: [1] }) + + expect(result.rows).toEqual([{ id: 1 }]) + expect(result.rowCount).toBe(1) + expect(sent[0]).toMatchObject({ + application: 'database', + message: 'database.query', + data: { + destination: 'tenant-a', + operationName: 'operation-a', + sql: 'SELECT $1::int as id', + values: [1], + }, + }) + expect(sent[0].data.requestId).toEqual(expect.any(String)) + }) + + it('runs transaction lifecycle through lock-bound messages', async () => { + const { sent } = installWattMessagingMock({ + 'database.beginTransaction': { lockId: 'lock-a' }, + 'database.lockedQuery': { rowCount: 1, rows: [{ ok: true }] }, + 'database.commitTransaction': { committed: true }, + }) + const connection = await getWattPostgresConnection(createConnectionOptions()) + + const tx = await connection.transaction({ isolation: 'serializable', readOnly: true }) + const result = await tx.query('SELECT 1') + await tx.commit() + + expect(result.rows).toEqual([{ ok: true }]) + expect(sent.map((message) => message.message)).toEqual([ + 'database.beginTransaction', + 'database.lockedQuery', + 'database.commitTransaction', + ]) + expect(sent[0].data).toMatchObject({ + destination: 'tenant-a', + isolationLevel: 'serializable', + readOnly: true, + }) + expect(sent[1].data).toMatchObject({ lockId: 'lock-a', sql: 'SELECT 1' }) + expect(tx.isCompleted()).toBe(true) + }) + + it('rolls back transactions through Database Watt messaging', async () => { + const { sent } = installWattMessagingMock({ + 'database.beginTransaction': { lockId: 'lock-a' }, + 'database.rollbackTransaction': { rolledBack: true }, + }) + const connection = await getWattPostgresConnection(createConnectionOptions()) + + const tx = await connection.transaction() + await tx.rollback() + + expect(sent.map((message) => message.message)).toEqual([ + 'database.beginTransaction', + 'database.rollbackTransaction', + ]) + expect(tx.isCompleted()).toBe(true) + }) + + it('maps PostgreSQL error responses back to pg DatabaseError', async () => { + installWattMessagingMock({ + 'database.query': { + code: 'POSTGRES_ERROR', + message: 'duplicate key value violates unique constraint', + sqlState: '23505', + }, + }) + const connection = await getWattPostgresConnection(createConnectionOptions()) + + await expect(connection.query('INSERT')).rejects.toMatchObject({ + code: '23505', + message: 'duplicate key value violates unique constraint', + }) + }) + + it('sends explicit cancellation when an AbortSignal fires', async () => { + let resolveQuery!: (value: unknown) => void + const { sent } = installWattMessagingMock({ + 'database.query': + new Promise((resolve) => { + resolveQuery = resolve + }), + 'database.cancel': { cancelled: true }, + }) + const connection = await getWattPostgresConnection(createConnectionOptions()) + const controller = new AbortController() + + const query = connection.query('SELECT pg_sleep(10)', { signal: controller.signal }) + controller.abort() + + await expect(query).rejects.toMatchObject({ name: 'AbortError', code: 'ABORT_ERR' }) + resolveQuery({ rowCount: 0, rows: [] }) + + expect(sent.map((message) => message.message)).toEqual(['database.query', 'database.cancel']) + expect(sent[1].data.requestId).toBe(sent[0].data.requestId) + }) + + it('creates superuser connections with service role credentials', async () => { + const { sent } = installWattMessagingMock({ + 'database.query': { rowCount: 1, rows: [] }, + }) + const connection = await getWattPostgresConnection(createConnectionOptions()) + + await connection.asSuperUser().query('SELECT 1') + + expect(sent[0].data.destination).toBe('tenant-a') + expect(connection.asSuperUser().role).toBe('service_role') + }) + + it('sends master executor queries through Database Watt messaging', async () => { + const { sent } = installWattMessagingMock({ + 'database.query': { rowCount: 1, rows: [{ id: 'master' }] }, + }) + const executor = new DatabaseWattPgExecutor('master', () => 'master-operation') + + const result = await executor.query<{ id: string }>('SELECT current_database()') + + expect(result.rows).toEqual([{ id: 'master' }]) + expect(sent[0]).toMatchObject({ + application: 'database', + message: 'database.query', + data: { + destination: 'master', + operationName: 'master-operation', + sql: 'SELECT current_database()', + }, + }) + }) + + it('runs master executor transactions through Database Watt messaging', async () => { + const { sent } = installWattMessagingMock({ + 'database.beginTransaction': { lockId: 'master-lock' }, + 'database.lockedQuery': { rowCount: 1, rows: [{ ok: true }] }, + 'database.commitTransaction': { committed: true }, + }) + const executor = new DatabaseWattPgExecutor('master') + + const tx = await executor.beginTransaction({ isolation: 'serializable', readOnly: true }) + await tx.query('SELECT 1') + await tx.commit() + + expect(sent.map((message) => message.message)).toEqual([ + 'database.beginTransaction', + 'database.lockedQuery', + 'database.commitTransaction', + ]) + expect(sent[0].data).toMatchObject({ + destination: 'master', + isolationLevel: 'serializable', + readOnly: true, + }) + expect(sent[1].data).toMatchObject({ lockId: 'master-lock', sql: 'SELECT 1' }) + }) +}) + +function createConnectionOptions(): TenantConnectionOptions { + return { + dbUrl: '', + isExternalPool: false, + isSingleUse: false, + maxConnections: 10, + operation: () => 'operation-a', + superUser: { + jwt: 'service-jwt', + payload: { role: 'service_role' }, + }, + tenantId: 'tenant-a', + user: { + jwt: 'user-jwt', + payload: { role: 'authenticated' }, + }, + } +} diff --git a/src/internal/database/watt-connection.ts b/src/internal/database/watt-connection.ts new file mode 100644 index 000000000..101aa696f --- /dev/null +++ b/src/internal/database/watt-connection.ts @@ -0,0 +1,382 @@ +import { getMessaging } from '@platformatic/globals' +import { TransactionOptions } from '@storage/database' +import { randomUUID } from 'node:crypto' +import { DatabaseError, QueryResult, QueryResultRow } from 'pg' +import { + PgExecutor, + PgQueryOptions, + PgStatement, + PgTenantConnection, + PgTenantConnectionLike, + PgTransaction, + PgTransactionalExecutor, + PgTransactionLike, +} from './pg-connection' +import { searchPath, TenantConnectionOptions } from './pool' + +type DatabaseErrorResponse = { + code: string + message: string + requestId?: string + operationName?: string + destination?: string + lockId?: string + sqlState?: string + stack?: string + connectionDiscarded?: boolean +} + +type QueryResponse = { + rows: T[] + rowCount: number +} + +type PgQueryArgument = PgQueryOptions | unknown[] + +const databaseApplicationId = 'database' + +export async function getWattPostgresConnection( + options: TenantConnectionOptions +): Promise { + return new WattPgTenantConnection(options) as unknown as PgTenantConnection +} + +class WattPgTenantConnection implements PgTenantConnectionLike { + readonly role: string + private readonly executor: DatabaseWattPgExecutor + private wattAbortSignal?: AbortSignal + + constructor(private readonly options: TenantConnectionOptions) { + this.role = options.user.payload.role || 'anon' + this.executor = new DatabaseWattPgExecutor(options.tenantId, options.operation) + } + + dispose(): Promise { + return Promise.resolve() + } + + setAbortSignal(signal: AbortSignal): void { + this.wattAbortSignal = signal + } + + getAbortSignal(): AbortSignal | undefined { + return this.wattAbortSignal + } + + async query( + statement: string | PgStatement, + options?: PgQueryArgument + ): Promise> { + return this.executor.query(statement, mergeSignalOptions(options, this.wattAbortSignal)) + } + + async beginTransaction(options?: TransactionOptions): Promise { + return this.executor.beginTransaction(options) + } + + asSuperUser(): PgTenantConnection { + const connection = new WattPgTenantConnection({ + ...this.options, + user: this.options.superUser, + }) + + if (this.wattAbortSignal) { + connection.setAbortSignal(this.wattAbortSignal) + } + + return connection as unknown as PgTenantConnection + } + + async transaction(opts?: TransactionOptions): Promise { + return this.beginTransaction(opts) as Promise + } + + async setScope(tnx: PgExecutor): Promise { + const headers = JSON.stringify(this.options.headers || {}) + await tnx.query({ + text: ` + SELECT + set_config('role', $1, true), + set_config('request.jwt.claim.role', $2, true), + set_config('request.jwt', $3, true), + set_config('request.jwt.claim.sub', $4, true), + set_config('request.jwt.claims', $5, true), + set_config('request.headers', $6, true), + set_config('request.method', $7, true), + set_config('request.path', $8, true), + set_config('storage.operation', $9, true), + set_config('storage.allow_delete_query', 'true', true), + set_config('search_path', $10, true); + `, + values: [ + this.role, + this.role, + this.options.user.jwt || '', + this.options.user.payload.sub || '', + JSON.stringify(this.options.user.payload), + headers, + this.options.method || '', + this.options.path || '', + this.options.operation?.() || '', + searchPath.join(','), + ], + }) + } +} + +export class DatabaseWattPgExecutor implements PgTransactionalExecutor { + private readonly destination: string + private readonly operation?: () => string | undefined + + constructor(destination: string, operation?: () => string | undefined) { + this.destination = destination + this.operation = operation + } + + async query( + statement: string | PgStatement, + options?: PgQueryArgument + ): Promise> { + const query = normalizeStatement(statement, Array.isArray(options) ? options : undefined) + const signal = Array.isArray(options) ? undefined : options?.signal + const response = await sendDatabaseMessage>( + 'database.query', + { + destination: this.destination, + operationName: this.operation?.(), + sql: query.text, + values: query.values, + }, + signal + ) + + return toPgQueryResult(response) + } + + async beginTransaction(options?: TransactionOptions): Promise { + const response = await sendDatabaseMessage<{ lockId: string }>('database.beginTransaction', { + destination: this.destination, + isolationLevel: options?.isolation, + operationName: this.operation?.(), + readOnly: options?.readOnly, + }) + + return new WattPgTransaction(response.lockId, this.operation) as unknown as PgTransaction + } +} + +class WattPgTransaction implements PgTransactionLike { + private wattCompleted = false + private readonly lockId: string + private readonly operation?: () => string | undefined + + constructor( + lockId: string, + operation?: () => string | undefined + ) { + this.lockId = lockId + this.operation = operation + } + + isCompleted(): boolean { + return this.wattCompleted + } + + async query( + statement: string | PgStatement, + options?: PgQueryArgument + ): Promise> { + if (this.wattCompleted) { + throw new Error('Cannot query a completed transaction') + } + + const query = normalizeStatement(statement, Array.isArray(options) ? options : undefined) + const signal = Array.isArray(options) ? undefined : options?.signal + const response = await sendDatabaseMessage>( + 'database.lockedQuery', + { + lockId: this.lockId, + operationName: this.operation?.(), + sql: query.text, + values: query.values, + }, + signal, + this.lockId + ) + + return toPgQueryResult(response) + } + + async commit(): Promise { + if (this.wattCompleted) { + return + } + + try { + await sendDatabaseMessage('database.commitTransaction', { lockId: this.lockId }) + } finally { + this.wattCompleted = true + } + } + + async rollback(): Promise { + if (this.wattCompleted) { + return + } + + try { + await sendDatabaseMessage('database.rollbackTransaction', { lockId: this.lockId }) + } finally { + this.wattCompleted = true + } + } +} + +function normalizeStatement(statement: string | PgStatement, values?: unknown[]): PgStatement { + if (typeof statement === 'string') { + return { text: statement, values } + } + + return statement +} + +function mergeSignalOptions( + options: PgQueryArgument | undefined, + signal: AbortSignal | undefined +): PgQueryArgument | undefined { + if (!signal || Array.isArray(options)) { + return options + } + + return { + ...options, + signal: options?.signal || signal, + } +} + +async function sendDatabaseMessage( + message: string, + data: Record, + signal?: AbortSignal, + lockId?: string +): Promise { + assertValidSignal(signal) + + const requestId = typeof data.requestId === 'string' ? data.requestId : randomUUID() + const payload = { ...data, requestId } + const request = getMessaging().send(databaseApplicationId, message, payload) + + if (!signal) { + const response = await request + return parseDatabaseMessageResponse(response) + } + + let abortListener: (() => void) | undefined + let settled = false + + const abortPromise = new Promise((_, reject) => { + abortListener = () => { + if (settled) { + return + } + + void getMessaging().send(databaseApplicationId, 'database.cancel', { requestId, lockId }).catch(() => undefined) + reject(createAbortError()) + } + + signal.addEventListener('abort', abortListener, { once: true }) + }) + + try { + const response = await Promise.race([request, abortPromise]) + return parseDatabaseMessageResponse(response) + } finally { + settled = true + if (abortListener) { + signal.removeEventListener('abort', abortListener) + } + } +} + +function parseDatabaseMessageResponse(response: unknown): T { + if (isDatabaseErrorResponse(response)) { + throw toDatabaseError(response) + } + + return response as T +} + +function assertValidSignal(signal?: AbortSignal): void { + if (!signal) { + return + } + + if (!(signal instanceof AbortSignal)) { + throw new Error('Expected signal to be an instance of AbortSignal') + } + + if (signal.aborted) { + throw createAbortError() + } +} + +function createAbortError(): Error & { code: string } { + const error = new Error('Query was aborted') as Error & { code: string } + error.name = 'AbortError' + error.code = 'ABORT_ERR' + return error +} + +function isDatabaseErrorResponse(response: unknown): response is DatabaseErrorResponse { + return Boolean( + response && + typeof response === 'object' && + typeof (response as { code?: unknown }).code === 'string' && + typeof (response as { message?: unknown }).message === 'string' + ) +} + +function toDatabaseError(response: DatabaseErrorResponse): Error { + if (response.code === 'POSTGRES_ERROR') { + const error = new DatabaseError(response.message, 0, 'error') + error.code = response.sqlState + error.stack = response.stack + return error + } + + if ( + response.code === 'CLIENT_TIMEOUT' || + response.code === 'SERVER_TIMEOUT' || + response.code === 'CONNECTION_TIMEOUT' || + response.code === 'ACQUIRE_TIMEOUT' || + response.code === 'MESSAGING_TIMEOUT' + ) { + const error = new DatabaseError(response.message, 0, 'error') + error.code = response.code === 'SERVER_TIMEOUT' ? '57014' : undefined + error.stack = response.stack + return error + } + + const error = new Error(response.message) as Error & { + code?: string + databaseCode?: string + databaseResponse?: DatabaseErrorResponse + } + error.code = response.code + error.databaseCode = response.code + error.databaseResponse = response + error.stack = response.stack + return error +} + +function toPgQueryResult( + response: QueryResponse +): QueryResult { + return { + command: '', + fields: [], + oid: 0, + rowCount: response.rowCount, + rows: response.rows, + } +} diff --git a/watt.database.json b/watt.database.json new file mode 100644 index 000000000..36fdf7171 --- /dev/null +++ b/watt.database.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://schemas.platformatic.dev/@platformatic/node/3.56.0.json", + "node": { + "main": "./dist/database/index.js", + "hasServer": false + } +} diff --git a/watt.json b/watt.json index 6165739eb..40d70d703 100644 --- a/watt.json +++ b/watt.json @@ -1,21 +1,30 @@ { - "$schema": "https://schemas.platformatic.dev/@platformatic/node/3.52.0.json", - "node": { - "main": "./dist/start/server.js" + "$schema": "https://schemas.platformatic.dev/@platformatic/runtime/3.56.0.json", + "entrypoint": "storage", + "exitOnUnhandledErrors": false, + "workers": "{WORKERS_NUM}", + "logger": { + "level": "{LOG_LEVEL}" }, - "runtime": { - "exitOnUnhandledErrors": false, - "workers": "{WORKERS_NUM}", - "logger": { - "level": "{LOG_LEVEL}" - }, - "health": { - "enabled": "{WATT_HEALTH_ENABLED}", - "maxELU": "{WATT_HEALTH_MAX_ELU}", - "gracePeriod": "{WATT_HEALTH_GRACE_PERIOD}", - "maxUnhealthyChecks": "{WATT_HEALTH_MAX_UNHEALTHY_CHECKS}", - "interval": "{WATT_HEALTH_INTERVAL}" + "health": { + "enabled": "{WATT_HEALTH_ENABLED}", + "maxELU": "{WATT_HEALTH_MAX_ELU}", + "gracePeriod": "{WATT_HEALTH_GRACE_PERIOD}", + "maxUnhealthyChecks": "{WATT_HEALTH_MAX_UNHEALTHY_CHECKS}", + "interval": "{WATT_HEALTH_INTERVAL}" + }, + "managementApi": "{PLT_MANAGEMENT_API}", + "applications": [ + { + "id": "storage", + "path": ".", + "config": "watt.storage.json" }, - "managementApi": "{PLT_MANAGEMENT_API}" - } + { + "id": "database", + "path": ".", + "config": "watt.database.json", + "workers": 1 + } + ] } diff --git a/watt.storage.json b/watt.storage.json new file mode 100644 index 000000000..3773e910d --- /dev/null +++ b/watt.storage.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://schemas.platformatic.dev/@platformatic/node/3.56.0.json", + "node": { + "main": "./dist/start/server.js", + "disableBuildInDevelopment": true + } +} From fd3200dbbdf92aa106872b098316cd5c31187327 Mon Sep 17 00:00:00 2001 From: Paolo Insogna Date: Fri, 12 Jun 2026 14:12:40 +0000 Subject: [PATCH 2/3] fixup Signed-off-by: Paolo Insogna --- acceptance/specs/database-watt.test.ts | 229 +++++++++++++++---------- 1 file changed, 141 insertions(+), 88 deletions(-) diff --git a/acceptance/specs/database-watt.test.ts b/acceptance/specs/database-watt.test.ts index 1fb43f972..ea684fe1b 100644 --- a/acceptance/specs/database-watt.test.ts +++ b/acceptance/specs/database-watt.test.ts @@ -1,14 +1,16 @@ import { randomUUID } from 'node:crypto' -import { describeAcceptance, encodePathSegments, getAcceptanceConfig } from '../support/config' -import { createRestClient } from '../support/http' -import { - cleanupRestResources, - createRestBucket, - requireServiceKey, - uniqueBucketName, - uniqueObjectKey, - uploadRestObject, -} from '../support/resources' +import { setupLoopbackMessaging } from '@platformatic/runtime' +import dotenv from 'dotenv' +import { describeAcceptance, getAcceptanceConfig } from '../support/config' +import { uniqueBucketName } from '../support/resources' + +dotenv.config({ path: '.env.test', override: false }) +dotenv.config({ path: '.env', override: false }) + +type ApplicationContext = { + close: () => Promise + isBackgroundApplication: boolean +} type DatabaseWattStats = { acquire: number @@ -40,6 +42,10 @@ type QueryRowsResponse = { rows: Array<{ value: number }> } +type BucketRowsResponse = { + rows: BucketResponse[] +} + type LockResponse = { lockId: string } @@ -48,16 +54,29 @@ type ErrorResponse = { code: string destination?: string message: string + sqlState?: string } const describeDatabaseWattAcceptance = process.env.ACCEPTANCE_DATABASE_WATT === 'true' ? describeAcceptance : describe.skip +let app: ApplicationContext | undefined +let messaging: ReturnType | undefined + +async function createDatabaseWattApp(): Promise { + const moduleUrl = new URL('../../src/database/index.ts', import.meta.url).href + const databaseApp = await import(moduleUrl) + return databaseApp.create() +} function testDestination(): string { return process.env.ACCEPTANCE_TENANT_ID || process.env.TENANT_ID || 'default' } function sendDatabaseMessage(message: string, payload: unknown): Promise { - return sendWattMessage('database', message, payload) + if (!messaging) { + throw new Error('Database Watt loopback messaging is not initialized') + } + + return messaging.send('database', message, payload) as Promise } function isDatabaseError(result: unknown): result is ErrorResponse { @@ -89,6 +108,75 @@ async function queryDatabaseWatt(destination = testDestination()): Promise { + const tx = await beginTransaction(destination) + + try { + await checkedResult( + sendDatabaseMessage('database.lockedQuery', { + lockId: tx.lockId, + requestId: randomUUID(), + sql: `SELECT set_config('storage.allow_delete_query', 'true', true)`, + }) + ) + await checkedResult( + sendDatabaseMessage('database.lockedQuery', { + lockId: tx.lockId, + requestId: randomUUID(), + sql: 'DELETE FROM storage.buckets WHERE id = $1', + values: [bucketName], + }) + ) + await checkedResult(sendDatabaseMessage('database.commitTransaction', { lockId: tx.lockId })) + } catch (error) { + await sendDatabaseMessage('database.rollbackTransaction', { lockId: tx.lockId }).catch(() => undefined) + throw error + } +} + +async function getBucket(bucketName: string, destination = testDestination()): Promise { + const result = await checkedResult( + sendDatabaseMessage('database.query', { + destination, + requestId: randomUUID(), + sql: 'SELECT id, name, public FROM storage.buckets WHERE id = $1', + values: [bucketName], + }) + ) + + return result.rows[0] +} + +async function insertBucket(bucketName: string, destination = testDestination()): Promise { + return sendDatabaseMessage('database.query', { + destination, + requestId: randomUUID(), + sql: `INSERT INTO storage.buckets (id, name, owner, public) VALUES ($1, $1, $2, false)`, + values: [bucketName, randomUUID()], + }) +} + +async function commitBucketDatabaseWatt(): Promise<{ bucketName: string }> { + const bucketName = uniqueBucketName('dbwatt-commit') + const tx = await beginTransaction() + + try { + await checkedResult( + sendDatabaseMessage('database.lockedQuery', { + lockId: tx.lockId, + requestId: randomUUID(), + sql: `INSERT INTO storage.buckets (id, name, owner, public) VALUES ($1, $1, $2, false)`, + values: [bucketName, randomUUID()], + }) + ) + await checkedResult(sendDatabaseMessage('database.commitTransaction', { lockId: tx.lockId })) + return { bucketName } + } catch (error) { + await sendDatabaseMessage('database.rollbackTransaction', { lockId: tx.lockId }).catch(() => undefined) + throw error + } +} + async function masterTransaction(): Promise<{ value: number | undefined }> { const tx = await beginTransaction('master') @@ -224,15 +312,28 @@ async function resetDatabaseWattStats(): Promise { } describeDatabaseWattAcceptance( - 'Database Watt E2E', + 'Database Watt PostgreSQL integration', { destructive: true, profiles: ['core'], }, () => { - it('executes stateless queries in the Database Watt worker', async () => { + beforeAll(async () => { + messaging = setupLoopbackMessaging('database-watt-acceptance') + app = await createDatabaseWattApp() + }) + + beforeEach(async () => { await resetDatabaseWattStats() + }) + + afterAll(async () => { + await app?.close() + app = undefined + messaging = undefined + }) + it('executes stateless queries in the Database Watt worker', async () => { const response = await queryDatabaseWatt() const stats = await getDatabaseWattStats() @@ -248,7 +349,6 @@ describeDatabaseWattAcceptance( return } - await resetDatabaseWattStats() const response = await queryDatabaseWatt('master') const stats = await getDatabaseWattStats() @@ -264,7 +364,6 @@ describeDatabaseWattAcceptance( return } - await resetDatabaseWattStats() const response = await masterTransaction() const stats = await getDatabaseWattStats() @@ -274,56 +373,38 @@ describeDatabaseWattAcceptance( expect(stats.commitTransaction).toBeGreaterThanOrEqual(1) }) - it('commits REST object changes through Database Watt transactions', async () => { - const client = createRestClient() - const token = requireServiceKey() - const bucketName = uniqueBucketName('dbwatt-commit') - const objectKey = uniqueObjectKey('dbwatt-commit') - await resetDatabaseWattStats() - + it('commits bucket changes through Database Watt transactions', async () => { + let bucketName: string | undefined try { - await createRestBucket(bucketName, { isPublic: false }) - await uploadRestObject(bucketName, objectKey, 'database-watt-commit') - - const read = await client.request('GET', `/object/${bucketName}/${encodePathSegments(objectKey)}`, { - expectedStatus: 200, - token, - }) + const committed = await commitBucketDatabaseWatt() + bucketName = committed.bucketName + const bucket = await getBucket(bucketName) const stats = await getDatabaseWattStats() - expect(read.body).toBe('database-watt-commit') + expect(bucket).toMatchObject({ id: bucketName, name: bucketName, public: false }) expect(stats.beginTransaction).toBeGreaterThanOrEqual(1) expect(stats.lockedQuery).toBeGreaterThanOrEqual(1) expect(stats.commitTransaction).toBeGreaterThanOrEqual(1) } finally { - await cleanupRestResources(bucketName, [objectKey], client) + if (bucketName) { + await cleanupBucket(bucketName) + } } }) it('rolls back failed transaction work and leaves no partial bucket state', async () => { - const client = createRestClient() - const token = requireServiceKey() - await resetDatabaseWattStats() - const rollback = await rollbackDatabaseWatt() const bucketName = rollback.bucketName expect(bucketName).toBeTruthy() - const lookup = await client.request('GET', `/bucket/${bucketName}`, { - expectedStatus: 400, - token, - }) + const bucket = await getBucket(bucketName) const stats = await getDatabaseWattStats() - expect(lookup.status).toBe(400) + expect(bucket).toBeUndefined() expect(stats.rollbackTransaction).toBeGreaterThanOrEqual(1) }) it('preserves nested savepoint semantics in Database Watt transactions', async () => { - const client = createRestClient() - const token = requireServiceKey() - await resetDatabaseWattStats() - const savepoint = await savepointDatabaseWatt() const outerBucket = savepoint.outerBucket const innerBucket = savepoint.innerBucket @@ -332,56 +413,37 @@ describeDatabaseWattAcceptance( expect(outerBucket).toBeTruthy() expect(innerBucket).toBeTruthy() - const outer = await client.request('GET', `/bucket/${outerBucket}`, { - expectedStatus: 200, - token, - }) - const inner = await client.request('GET', `/bucket/${innerBucket}`, { - expectedStatus: 400, - token, - }) + const outer = await getBucket(outerBucket) + const inner = await getBucket(innerBucket) const stats = await getDatabaseWattStats() - expect(outer.json?.id).toBe(outerBucket) - expect(inner.status).toBe(400) + expect(outer?.id).toBe(outerBucket) + expect(inner).toBeUndefined() expect(stats.lockedQuery).toBeGreaterThanOrEqual(3) expect(stats.commitTransaction).toBeGreaterThanOrEqual(1) } finally { if (outerBucket) { - await cleanupRestResources(outerBucket, [], client) + await cleanupBucket(outerBucket) } } }) - it('preserves storage error mapping when Database Watt returns PostgreSQL errors', async () => { - const client = createRestClient() - const token = requireServiceKey() + it('preserves PostgreSQL error mapping when Database Watt returns PostgreSQL errors', async () => { const bucketName = uniqueBucketName('dbwatt-error') - await resetDatabaseWattStats() try { - await createRestBucket(bucketName, { isPublic: false }) - const duplicate = await client.request('POST', '/bucket', { - body: { - id: bucketName, - name: bucketName, - public: false, - }, - expectedStatus: 400, - token, - }) + await checkedResult(insertBucket(bucketName)) + const duplicate = await insertBucket(bucketName) as ErrorResponse const stats = await getDatabaseWattStats() - expect(duplicate.status).toBe(400) - expect(stats.lockedQuery).toBeGreaterThanOrEqual(1) + expect(duplicate).toMatchObject({ code: 'POSTGRES_ERROR', sqlState: '23505' }) + expect(stats.query).toBeGreaterThanOrEqual(2) } finally { - await cleanupRestResources(bucketName, [], client) + await cleanupBucket(bucketName) } }) it('translates request aborts into Database Watt cancellation', async () => { - await resetDatabaseWattStats() - const response = await sleepDatabaseWatt() const stats = await getDatabaseWattStats() @@ -397,7 +459,6 @@ describeDatabaseWattAcceptance( return } - await resetDatabaseWattStats() const response = await missingDestinationDatabaseWatt() expect(response).toMatchObject({ code: 'DESTINATION_UNKNOWN' }) @@ -405,8 +466,6 @@ describeDatabaseWattAcceptance( }) it('handles concurrent Database Watt query load', async () => { - await resetDatabaseWattStats() - const response = await concurrentQueriesDatabaseWatt() const stats = await getDatabaseWattStats() @@ -416,8 +475,6 @@ describeDatabaseWattAcceptance( it('exercises multitenant destination resolution when the target is multitenant', async () => { const config = getAcceptanceConfig() - const client = createRestClient() - const token = requireServiceKey(config) const bucketName = uniqueBucketName('dbwatt-tenant') if (!config.tenantId) { @@ -425,19 +482,15 @@ describeDatabaseWattAcceptance( return } - await resetDatabaseWattStats() try { - await createRestBucket(bucketName, { isPublic: false }) - const bucket = await client.request('GET', `/bucket/${bucketName}`, { - expectedStatus: 200, - token, - }) + await checkedResult(insertBucket(bucketName, config.tenantId)) + const bucket = await getBucket(bucketName, config.tenantId) const stats = await getDatabaseWattStats() - expect(bucket.json?.id).toBe(bucketName) - expect(stats.beginTransaction).toBeGreaterThanOrEqual(1) + expect(bucket?.id).toBe(bucketName) + expect(stats.query).toBeGreaterThanOrEqual(2) } finally { - await cleanupRestResources(bucketName, [], client) + await cleanupBucket(bucketName, config.tenantId) } }) } From 58b8aaf228f00a43c93b583b3500bf47de495af9 Mon Sep 17 00:00:00 2001 From: Paolo Insogna Date: Mon, 15 Jun 2026 05:46:51 +0000 Subject: [PATCH 3/3] fixup Signed-off-by: Paolo Insogna --- src/admin-app.test.ts | 2 +- src/database/config.ts | 2 + src/database/destinations.ts | 2 +- src/database/pools.ts | 25 ++++++-- src/database/ssl.ts | 8 ++- src/database/tests/destinations.test.ts | 20 +++++++ src/database/tests/index.test.ts | 42 ++++++++----- src/database/tests/ssl.test.ts | 24 ++++++++ src/internal/database/watt-connection.test.ts | 59 ++++++++++++++----- src/internal/database/watt-connection.ts | 13 ++-- 10 files changed, 153 insertions(+), 44 deletions(-) create mode 100644 src/database/tests/destinations.test.ts create mode 100644 src/database/tests/ssl.test.ts diff --git a/src/admin-app.test.ts b/src/admin-app.test.ts index 9a443e69c..3d0a6baba 100644 --- a/src/admin-app.test.ts +++ b/src/admin-app.test.ts @@ -1,4 +1,4 @@ -import { vi } from 'vitest' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' function mockAdminAppDependencies() { vi.doMock('./config', () => ({ diff --git a/src/database/config.ts b/src/database/config.ts index 3a6601193..a74aec7bb 100644 --- a/src/database/config.ts +++ b/src/database/config.ts @@ -22,6 +22,7 @@ export type DatabaseConfig = { maxResultRows: number maxSerializedRequestBytes: number maxSqlBytes: number + poolIsExternal: boolean poolConnectionString?: string poolMode?: string rootCert?: string @@ -73,6 +74,7 @@ export function readConfig(env: NodeJS.ProcessEnv = process.env): DatabaseConfig 10 * 1024 * 1024 ), maxSqlBytes: readPositiveInteger(env.DATABASE_WATT_MAX_SQL_BYTES, 1024 * 1024), + poolIsExternal: Boolean(env.DATABASE_POOL_URL), poolConnectionString: env.DATABASE_POOL_URL || env.DATABASE_URL, poolMode: env.DATABASE_POOL_MODE, rootCert: readRootCert(env.DATABASE_SSL_ROOT_CERT), diff --git a/src/database/destinations.ts b/src/database/destinations.ts index fc5b3c182..4d96fea0f 100644 --- a/src/database/destinations.ts +++ b/src/database/destinations.ts @@ -36,7 +36,7 @@ export class DestinationResolver { return { connectionString, id: destination, - isExternalPool: Boolean(process.env.DATABASE_POOL_URL), + isExternalPool: this.config.poolIsExternal, maxConnections: this.config.destinationMaxConnections, poolMode: this.config.poolMode, } diff --git a/src/database/pools.ts b/src/database/pools.ts index ae50e4c5e..f4106b96a 100644 --- a/src/database/pools.ts +++ b/src/database/pools.ts @@ -21,13 +21,17 @@ export class PoolRegistry { private readonly config: DatabaseConfig private readonly pools = new Map() private pendingGlobalAcquisitions = 0 + private cachedStats?: PoolRegistryStats private readonly evictionInterval: NodeJS.Timeout constructor(config: DatabaseConfig) { this.config = config - this.evictionInterval = setInterval(() => { - void this.evictIdlePools() - }, Math.max(config.idlePoolTimeoutMs, 1_000)) + this.evictionInterval = setInterval( + () => { + void this.evictIdlePools() + }, + Math.max(config.idlePoolTimeoutMs, 1_000) + ) this.evictionInterval.unref() } @@ -75,6 +79,10 @@ export class PoolRegistry { } getStats(): PoolRegistryStats { + if (this.cachedStats) { + return this.cachedStats + } + let inUseConnections = 0 let totalConnections = 0 let waitingRequests = 0 @@ -85,18 +93,25 @@ export class PoolRegistry { waitingRequests += entry.pool.waitingCount } - return { + const stats = { inUseConnections, pools: this.pools.size, totalConnections, waitingRequests, } + this.cachedStats = stats + queueMicrotask(() => { + this.cachedStats = undefined + }) + + return stats } async close(): Promise { clearInterval(this.evictionInterval) const pools = [...this.pools.values()].map((entry) => entry.pool) this.pools.clear() + this.cachedStats = undefined await Promise.allSettled(pools.map((pool) => pool.end())) } @@ -132,6 +147,7 @@ export class PoolRegistry { } this.pools.set(destination.id, entry) + this.cachedStats = undefined return entry } @@ -166,6 +182,7 @@ export class PoolRegistry { } this.pools.delete(destination) + this.cachedStats = undefined toEvict.push(entry.pool) } diff --git a/src/database/ssl.ts b/src/database/ssl.ts index 810db9e4e..68df2ab84 100644 --- a/src/database/ssl.ts +++ b/src/database/ssl.ts @@ -1,7 +1,7 @@ export function getSslSettings( connectionString: string, rootCert?: string -): { ca?: string; rejectUnauthorized?: boolean } | false | undefined { +): { ca?: string; rejectUnauthorized?: boolean } | boolean | undefined { const sslMode = getSslMode(connectionString) if (sslMode === 'disable') { @@ -14,7 +14,11 @@ export function getSslSettings( } } - if (sslMode === 'require' || sslMode === 'prefer') { + if (sslMode === 'require') { + return true + } + + if (sslMode === 'prefer') { return { rejectUnauthorized: false, } diff --git a/src/database/tests/destinations.test.ts b/src/database/tests/destinations.test.ts new file mode 100644 index 000000000..fe834a535 --- /dev/null +++ b/src/database/tests/destinations.test.ts @@ -0,0 +1,20 @@ +import { describe, expect, it } from 'vitest' +import { readConfig } from '../config.js' +import { DestinationResolver } from '../destinations.js' + +describe('database destination resolution', () => { + it('derives single-tenant external pool state from parsed config', async () => { + const resolver = new DestinationResolver( + readConfig({ + DATABASE_POOL_URL: 'postgres://pooler', + }) + ) + + const destination = await resolver.resolve('default') + + expect(destination).toMatchObject({ + connectionString: 'postgres://pooler', + isExternalPool: true, + }) + }) +}) diff --git a/src/database/tests/index.test.ts b/src/database/tests/index.test.ts index da8ae4997..296d76c9d 100644 --- a/src/database/tests/index.test.ts +++ b/src/database/tests/index.test.ts @@ -3,8 +3,6 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import type { DatabaseErrorResponse } from '../errors.js' import type { ApplicationContext } from '../index.js' -type Handler = (data: unknown) => Promise - type MockClient = { queries: Array<{ sql: string; values?: unknown[] }> query: ReturnType @@ -12,10 +10,14 @@ type MockClient = { } type MockedEnvironment = { - app: ApplicationContext, + app: ApplicationContext messaging: ReturnType clients: MockClient[] - pools: Array<{ config: Record; ended: boolean; queries: Array<{ sql: string; values?: unknown[] }> }> + pools: Array<{ + config: Record + ended: boolean + queries: Array<{ sql: string; values?: unknown[] }> + }> } function createMockClient(rows: unknown[]): MockClient { @@ -31,14 +33,11 @@ function createMockClient(rows: unknown[]): MockClient { return client } -async function loadApp(options: { - env?: Record - queryRows?: unknown[] - tenantRows?: unknown[] -} = {}): Promise { +async function loadApp( + options: { env?: Record; queryRows?: unknown[]; tenantRows?: unknown[] } = {} +): Promise { vi.resetModules() - const handlers = new Map() const clients: MockClient[] = [] const pools: MockedEnvironment['pools'] = [] const queryRows = options.queryRows || [{ ok: true }] @@ -100,7 +99,7 @@ async function loadApp(options: { })) // We need dynamic import due to the mocking of PostgreSQL modules above - const {create} = await import('../index.js') + const { create } = await import('../index.js') const messaging = setupLoopbackMessaging('db') const app = create() @@ -120,7 +119,7 @@ describe('database Watt application messaging handlers', () => { it('registers prefixed handlers and exposes no server', async () => { const { app } = await loadApp() - expect(app.isBackgroundApplication).toBe(true) + expect(app.isBackgroundApplication).toBe(true) }) it('executes stateless queries against the single-tenant destination', async () => { @@ -138,6 +137,19 @@ describe('database Watt application messaging handlers', () => { expect(clients[0].release).toHaveBeenCalledWith(undefined) }) + it('marks single-tenant DATABASE_POOL_URL destinations as external pools', async () => { + const { messaging, pools } = await loadApp({ + env: { DATABASE_POOL_URL: 'postgres://pooler' }, + }) + + await messaging.send('database', 'database.query', { + destination: 'default', + sql: 'SELECT 1', + }) + + expect(pools[0].config).toMatchObject({ connectionString: 'postgres://pooler' }) + }) + it('returns validation errors from malformed requests', async () => { const { messaging } = await loadApp() @@ -200,7 +212,9 @@ describe('database Watt application messaging handlers', () => { lockId: begin.lockId, sql: 'SELECT 1', }) - const commit = await messaging.send('database', 'database.commitTransaction', { lockId: begin.lockId }) + const commit = await messaging.send('database', 'database.commitTransaction', { + lockId: begin.lockId, + }) expect(commit).toEqual({ committed: true }) expect(clients[0].queries.map((query) => query.sql)).toEqual([ @@ -300,5 +314,3 @@ describe('database Watt application messaging handlers', () => { }) }) }) - - diff --git a/src/database/tests/ssl.test.ts b/src/database/tests/ssl.test.ts new file mode 100644 index 000000000..a1aaf2543 --- /dev/null +++ b/src/database/tests/ssl.test.ts @@ -0,0 +1,24 @@ +import { describe, expect, it } from 'vitest' +import { getSslSettings } from '../ssl.js' + +describe('database SSL settings', () => { + it('disables SSL when sslmode=disable', () => { + expect(getSslSettings('postgres://user:pass@localhost/db?sslmode=disable')).toBe(false) + }) + + it('uses certificate verification for sslmode=require without a root cert', () => { + expect(getSslSettings('postgres://user:pass@localhost/db?sslmode=require')).toBe(true) + }) + + it('uses the configured root certificate when present', () => { + expect(getSslSettings('postgres://user:pass@localhost/db?sslmode=require', '')).toEqual({ + ca: '', + }) + }) + + it('keeps sslmode=prefer compatible with poolers that use self-signed certificates', () => { + expect(getSslSettings('postgres://user:pass@localhost/db?sslmode=prefer')).toEqual({ + rejectUnauthorized: false, + }) + }) +}) diff --git a/src/internal/database/watt-connection.test.ts b/src/internal/database/watt-connection.test.ts index 3b60e4fa1..00c599854 100644 --- a/src/internal/database/watt-connection.test.ts +++ b/src/internal/database/watt-connection.test.ts @@ -1,10 +1,7 @@ import { removeGlobals, updateGlobals } from '@platformatic/globals' -import { describe, expect, it } from 'vitest' +import { afterEach, describe, expect, it, vi } from 'vitest' import type { TenantConnectionOptions } from './pool' -import { - DatabaseWattPgExecutor, - getWattPostgresConnection, -} from './watt-connection' +import { DatabaseWattPgExecutor, getWattPostgresConnection } from './watt-connection' type SentWattMessage = { application: string @@ -12,19 +9,21 @@ type SentWattMessage = { message: string } -function installWattMessagingMock( - responses: Record = {} -): { sent: SentWattMessage[] } { +function installWattMessagingMock(responses: Record = {}): { + sent: SentWattMessage[] +} { const sent: SentWattMessage[] = [] updateGlobals({ messaging: { + handle: vi.fn(), + notify: vi.fn(), send: vi.fn(async (application: string, message: string, data: Record) => { sent.push({ application, data, message }) const response = responses[message] return response instanceof Promise ? response : response }), - } as unknown as any + }, }) return { sent } @@ -41,7 +40,10 @@ describe('Watt PostgreSQL connection adapter', () => { }) const connection = await getWattPostgresConnection(createConnectionOptions()) - const result = await connection.query<{ id: number }>({ text: 'SELECT $1::int as id', values: [1] }) + const result = await connection.query<{ id: number }>({ + text: 'SELECT $1::int as id', + values: [1], + }) expect(result.rows).toEqual([{ id: 1 }]) expect(result.rowCount).toBe(1) @@ -118,13 +120,42 @@ describe('Watt PostgreSQL connection adapter', () => { }) }) + it('preserves timeout response codes on pg DatabaseError', async () => { + installWattMessagingMock({ + 'database.query': { + code: 'ACQUIRE_TIMEOUT', + message: 'Timed out acquiring database connection', + }, + }) + const connection = await getWattPostgresConnection(createConnectionOptions()) + + await expect(connection.query('SELECT 1')).rejects.toMatchObject({ + code: 'ACQUIRE_TIMEOUT', + message: 'Timed out acquiring database connection', + }) + }) + + it('maps server timeouts to PostgreSQL query-canceled SQLSTATE', async () => { + installWattMessagingMock({ + 'database.query': { + code: 'SERVER_TIMEOUT', + message: 'canceling statement due to statement timeout', + }, + }) + const connection = await getWattPostgresConnection(createConnectionOptions()) + + await expect(connection.query('SELECT pg_sleep(10)')).rejects.toMatchObject({ + code: '57014', + message: 'canceling statement due to statement timeout', + }) + }) + it('sends explicit cancellation when an AbortSignal fires', async () => { let resolveQuery!: (value: unknown) => void const { sent } = installWattMessagingMock({ - 'database.query': - new Promise((resolve) => { - resolveQuery = resolve - }), + 'database.query': new Promise((resolve) => { + resolveQuery = resolve + }), 'database.cancel': { cancelled: true }, }) const connection = await getWattPostgresConnection(createConnectionOptions()) diff --git a/src/internal/database/watt-connection.ts b/src/internal/database/watt-connection.ts index 101aa696f..710c87ea7 100644 --- a/src/internal/database/watt-connection.ts +++ b/src/internal/database/watt-connection.ts @@ -1,6 +1,6 @@ +import { randomUUID } from 'node:crypto' import { getMessaging } from '@platformatic/globals' import { TransactionOptions } from '@storage/database' -import { randomUUID } from 'node:crypto' import { DatabaseError, QueryResult, QueryResultRow } from 'pg' import { PgExecutor, @@ -170,10 +170,7 @@ class WattPgTransaction implements PgTransactionLike { private readonly lockId: string private readonly operation?: () => string | undefined - constructor( - lockId: string, - operation?: () => string | undefined - ) { + constructor(lockId: string, operation?: () => string | undefined) { this.lockId = lockId this.operation = operation } @@ -280,7 +277,9 @@ async function sendDatabaseMessage( return } - void getMessaging().send(databaseApplicationId, 'database.cancel', { requestId, lockId }).catch(() => undefined) + void getMessaging() + .send(databaseApplicationId, 'database.cancel', { requestId, lockId }) + .catch(() => undefined) reject(createAbortError()) } @@ -352,7 +351,7 @@ function toDatabaseError(response: DatabaseErrorResponse): Error { response.code === 'MESSAGING_TIMEOUT' ) { const error = new DatabaseError(response.message, 0, 'error') - error.code = response.code === 'SERVER_TIMEOUT' ? '57014' : undefined + error.code = response.code === 'SERVER_TIMEOUT' ? '57014' : response.code error.stack = response.stack return error }