diff --git a/.github/workflows/publish-packages.yaml b/.github/workflows/publish-packages.yaml new file mode 100644 index 0000000..4bae3c4 --- /dev/null +++ b/.github/workflows/publish-packages.yaml @@ -0,0 +1,66 @@ +name: "Publish packages" + +on: + push: + tags: + - "shared-utils-v*" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +permissions: + contents: read + packages: write + +jobs: + publish-shared-utils: + name: "Publish @nhsdigital/nhs-notify-shared-utils" + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - name: "Checkout code" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: "Set CI/CD variables" + id: variables + run: | + echo "nodejs_version=$(grep "^nodejs\s" .tool-versions | cut -f2 -d' ')" >> "$GITHUB_OUTPUT" + echo "pnpm_version=$(grep "^pnpm\s" .tool-versions | cut -f2 -d' ')" >> "$GITHUB_OUTPUT" + + - name: "Node install and setup" + uses: ./.github/actions/node-install + with: + node-version: ${{ steps.variables.outputs.nodejs_version }} + pnpm-version: ${{ steps.variables.outputs.pnpm_version }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: "Verify tag version matches package version" + run: | + TAG_VERSION="${GITHUB_REF_NAME#shared-utils-v}" + PKG_VERSION="$(node -p "require('./packages/shared-utils/package.json').version")" + echo "Tag version: ${TAG_VERSION}" + echo "Package version: ${PKG_VERSION}" + if [ "${TAG_VERSION}" != "${PKG_VERSION}" ]; then + echo "::error::Tag version (${TAG_VERSION}) does not match package version (${PKG_VERSION})" >&2 + exit 1 + fi + + - name: "Install dependencies" + run: pnpm install --frozen-lockfile + + - name: "Lint" + run: pnpm --filter @nhsdigital/nhs-notify-shared-utils run lint + + - name: "Typecheck" + run: pnpm --filter @nhsdigital/nhs-notify-shared-utils run typecheck + + - name: "Unit tests (100% coverage)" + run: pnpm --filter @nhsdigital/nhs-notify-shared-utils run test:unit + + - name: "Build" + run: pnpm --filter @nhsdigital/nhs-notify-shared-utils run build + + - name: "Publish to GitHub Packages" + run: pnpm --filter @nhsdigital/nhs-notify-shared-utils publish --no-git-checks diff --git a/eslint.config.mjs b/eslint.config.mjs index 190464b..38f89f5 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -68,6 +68,7 @@ export default defineConfig([ project: [ 'src/lambdas/*/tsconfig.json', 'src/utils/tsconfig.json', + 'packages/*/tsconfig.json', ], }), ], @@ -217,7 +218,7 @@ export default defineConfig([ }, }, { - files: ['src/utils/**', '**/jest.config.ts'], + files: ['src/utils/**', '**/jest.config.ts', 'packages/**'], rules: { 'no-relative-import-paths/no-relative-import-paths': 0, 'import-x/no-relative-packages': 0, diff --git a/packages/shared-utils/README.md b/packages/shared-utils/README.md new file mode 100644 index 0000000..53e6f7b --- /dev/null +++ b/packages/shared-utils/README.md @@ -0,0 +1,30 @@ +# @nhsdigital/nhs-notify-shared-utils + +This package contains **generic** technical helpers (logging, Lambda +helpers, integration test support) for use across bounded contexts. + +## Exports + +| Subpath | Purpose | Docs | +| --------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------ | +| `./logger` | Generic pino-backed `Logger` with redaction support | [logger](src/logger/README.md) | +| `./lambda-utils` | `requireEnv`, `MissingEnvironmentVariableError`, `formatZodIssues`, SQS attribute readers | [lambda-utils](src/lambda-utils/README.md) | +| `./test-support` | Low level Integration test-support utilities - deployment/naming, polling, event factories | [test-support](src/test-support/README.md) | +| `./test-support/{cloudwatch,sqs,s3,dynamodb,eventbridge}` | Per-service AWS client factories and helpers | [test-support](src/test-support/README.md) | +| `./s3-json` | S3 get-JSON-and-validate helper | [s3-json](src/s3-json/README.md) | + +## Scripts + +```sh +pnpm run build # rm -rf dist && tsc +pnpm run lint # eslint . +pnpm run typecheck # tsc --noEmit +pnpm run test:unit # jest (100% coverage) +pnpm run verify # lint && typecheck && test:unit +``` + +## Release + +Publishing is tag-driven. Pushing a tag of the form `shared-utils-vX.Y.Z` +triggers the publish workflow, which requires an equivalent version bump to +`version` in `package.json`. diff --git a/packages/shared-utils/jest.config.ts b/packages/shared-utils/jest.config.ts new file mode 100644 index 0000000..bcffa79 --- /dev/null +++ b/packages/shared-utils/jest.config.ts @@ -0,0 +1,22 @@ +import type { Config } from 'jest'; +import { baseJestConfig } from '../../jest.config.base'; + +const sharedUtilsJestConfig: Config = { + ...baseJestConfig, + + coverageThreshold: { + global: { + branches: 100, + functions: 100, + lines: 100, + statements: 100, + }, + }, + + coveragePathIgnorePatterns: [ + ...(baseJestConfig.coveragePathIgnorePatterns ?? []), + 'index.ts', + ], +}; + +export default sharedUtilsJestConfig; diff --git a/packages/shared-utils/package.json b/packages/shared-utils/package.json new file mode 100644 index 0000000..5174ec7 --- /dev/null +++ b/packages/shared-utils/package.json @@ -0,0 +1,124 @@ +{ + "name": "@nhsdigital/nhs-notify-shared-utils", + "version": "0.1.0", + "description": "Generic technical utilities (logging, lambda helpers, integration test support) shared across NHS Notify bounded contexts", + "license": "MIT", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "source": "./src/index.ts", + "default": "./dist/index.js" + }, + "./lambda-utils": { + "types": "./dist/lambda-utils/index.d.ts", + "source": "./src/lambda-utils/index.ts", + "default": "./dist/lambda-utils/index.js" + }, + "./logger": { + "types": "./dist/logger/index.d.ts", + "source": "./src/logger/index.ts", + "default": "./dist/logger/index.js" + }, + "./test-support": { + "types": "./dist/test-support/index.d.ts", + "source": "./src/test-support/index.ts", + "default": "./dist/test-support/index.js" + }, + "./test-support/cloudwatch": { + "types": "./dist/test-support/cloudwatch.d.ts", + "source": "./src/test-support/cloudwatch.ts", + "default": "./dist/test-support/cloudwatch.js" + }, + "./test-support/dynamodb": { + "types": "./dist/test-support/dynamodb.d.ts", + "source": "./src/test-support/dynamodb.ts", + "default": "./dist/test-support/dynamodb.js" + }, + "./test-support/eventbridge": { + "types": "./dist/test-support/eventbridge.d.ts", + "source": "./src/test-support/eventbridge.ts", + "default": "./dist/test-support/eventbridge.js" + }, + "./test-support/s3": { + "types": "./dist/test-support/s3.d.ts", + "source": "./src/test-support/s3.ts", + "default": "./dist/test-support/s3.js" + }, + "./test-support/sqs": { + "types": "./dist/test-support/sqs.d.ts", + "source": "./src/test-support/sqs.ts", + "default": "./dist/test-support/sqs.js" + }, + "./s3-json": { + "types": "./dist/s3-json/index.d.ts", + "source": "./src/s3-json/index.ts", + "default": "./dist/s3-json/index.js" + } + }, + "files": [ + "dist" + ], + "publishConfig": { + "access": "public", + "registry": "https://npm.pkg.github.com" + }, + "scripts": { + "build": "rm -rf dist && tsc -p tsconfig.build.json", + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "test:unit": "jest", + "typecheck": "tsc --noEmit", + "verify": "pnpm run lint && pnpm run typecheck && pnpm run test:unit" + }, + "peerDependencies": { + "@aws-sdk/client-cloudwatch-logs": "catalog:aws", + "@aws-sdk/client-dynamodb": "catalog:aws", + "@aws-sdk/client-eventbridge": "catalog:aws", + "@aws-sdk/client-s3": "catalog:aws", + "@aws-sdk/client-sqs": "catalog:aws", + "@aws-sdk/lib-dynamodb": "catalog:aws", + "pino": "catalog:runtime" + }, + "peerDependenciesMeta": { + "@aws-sdk/client-cloudwatch-logs": { + "optional": true + }, + "@aws-sdk/client-dynamodb": { + "optional": true + }, + "@aws-sdk/client-eventbridge": { + "optional": true + }, + "@aws-sdk/client-s3": { + "optional": true + }, + "@aws-sdk/client-sqs": { + "optional": true + }, + "@aws-sdk/lib-dynamodb": { + "optional": true + } + }, + "devDependencies": { + "@aws-sdk/client-cloudwatch-logs": "catalog:aws", + "@aws-sdk/client-dynamodb": "catalog:aws", + "@aws-sdk/client-eventbridge": "catalog:aws", + "@aws-sdk/client-s3": "catalog:aws", + "@aws-sdk/client-sqs": "catalog:aws", + "@aws-sdk/lib-dynamodb": "catalog:aws", + "@tsconfig/node22": "catalog:tools", + "@types/jest": "catalog:test", + "@types/node": "catalog:tools", + "eslint": "catalog:lint", + "jest": "catalog:test", + "pino": "catalog:runtime", + "ts-jest": "catalog:test", + "typescript": "catalog:tools" + }, + "engines": { + "node": ">=22.15.1" + }, + "private": false +} diff --git a/packages/shared-utils/src/index.ts b/packages/shared-utils/src/index.ts new file mode 100644 index 0000000..c5c68c3 --- /dev/null +++ b/packages/shared-utils/src/index.ts @@ -0,0 +1,2 @@ +export * from './lambda-utils'; +export * from './logger'; diff --git a/packages/shared-utils/src/lambda-utils/README.md b/packages/shared-utils/src/lambda-utils/README.md new file mode 100644 index 0000000..4275658 --- /dev/null +++ b/packages/shared-utils/src/lambda-utils/README.md @@ -0,0 +1,50 @@ +# `@nhsdigital/nhs-notify-shared-utils/lambda-utils` + +Small, dependency-light helpers for Lambda handlers. + +## Import + +```ts +import { + CORRELATION_ID_ATTRIBUTE, + formatZodIssues, + MissingEnvironmentVariableError, + readSqsStringAttribute, + requireEnv, +} from '@nhsdigital/nhs-notify-shared-utils/lambda-utils'; +``` + +## `requireEnv` + +Reads a required environment variable. Throws +`MissingEnvironmentVariableError` when the variable is unset or empty. + +```ts +const tableName = requireEnv('TABLE_NAME'); +``` + +## `readSqsStringAttribute` + +Reads a `String` message attribute from an SQS record, or `undefined` when the +attribute is absent or not a string. `CORRELATION_ID_ATTRIBUTE` is the shared +`correlationId` attribute name. + +```ts +const correlationId = readSqsStringAttribute(record, CORRELATION_ID_ATTRIBUTE); +``` + +The record only needs a `messageAttributes` map (see `SqsRecordLike`), so the +helper stays decoupled from the `aws-lambda` types. + +## `formatZodIssues` + +Turns an array of Zod issues into a single readable string. It is pure: it does +not log or throw. Any `ZodError.issues` array is accepted. + +```ts +const result = schema.safeParse(input); +if (!result.success) { + throw new Error(`Invalid input — ${formatZodIssues(result.error.issues)}`); +} +// "items.0.id: Required; name: Expected string" +``` diff --git a/packages/shared-utils/src/lambda-utils/__tests__/format-zod-issues.test.ts b/packages/shared-utils/src/lambda-utils/__tests__/format-zod-issues.test.ts new file mode 100644 index 0000000..9e57cf3 --- /dev/null +++ b/packages/shared-utils/src/lambda-utils/__tests__/format-zod-issues.test.ts @@ -0,0 +1,36 @@ +import { formatZodIssues } from '../format-zod-issues'; + +describe('formatZodIssues', () => { + it('returns an empty string for an empty issue list', () => { + expect(formatZodIssues([])).toBe(''); + }); + + it('formats a single issue with a dotted path', () => { + expect( + formatZodIssues([{ path: ['channelId'], message: 'Required' }]), + ).toBe('channelId: Required'); + }); + + it('joins a nested path with dots and coerces numeric segments', () => { + expect( + formatZodIssues([ + { path: ['items', 0, 'id'], message: 'Expected string' }, + ]), + ).toBe('items.0.id: Expected string'); + }); + + it('omits the path prefix when the issue path is empty', () => { + expect(formatZodIssues([{ path: [], message: 'Invalid input' }])).toBe( + 'Invalid input', + ); + }); + + it('joins multiple issues with a semicolon separator', () => { + expect( + formatZodIssues([ + { path: ['a'], message: 'first' }, + { path: [], message: 'second' }, + ]), + ).toBe('a: first; second'); + }); +}); diff --git a/packages/shared-utils/src/lambda-utils/__tests__/require-env.test.ts b/packages/shared-utils/src/lambda-utils/__tests__/require-env.test.ts new file mode 100644 index 0000000..36b80b4 --- /dev/null +++ b/packages/shared-utils/src/lambda-utils/__tests__/require-env.test.ts @@ -0,0 +1,29 @@ +import { MissingEnvironmentVariableError, requireEnv } from '../require-env'; + +describe('requireEnv', () => { + const ORIGINAL_ENV = { ...process.env }; + + afterEach(() => { + process.env = { ...ORIGINAL_ENV }; + }); + + it('returns the value when the variable is set', () => { + process.env.TEST_VAR = 'hello'; + expect(requireEnv('TEST_VAR')).toBe('hello'); + }); + + it('throws MissingEnvironmentVariableError when the variable is undefined', () => { + delete process.env.MISSING_VAR; + expect(() => requireEnv('MISSING_VAR')).toThrow( + MissingEnvironmentVariableError, + ); + expect(() => requireEnv('MISSING_VAR')).toThrow('MISSING_VAR is required'); + }); + + it('throws MissingEnvironmentVariableError when the variable is empty string', () => { + process.env.EMPTY_VAR = ''; + expect(() => requireEnv('EMPTY_VAR')).toThrow( + MissingEnvironmentVariableError, + ); + }); +}); diff --git a/packages/shared-utils/src/lambda-utils/__tests__/sqs.test.ts b/packages/shared-utils/src/lambda-utils/__tests__/sqs.test.ts new file mode 100644 index 0000000..d2ae7cd --- /dev/null +++ b/packages/shared-utils/src/lambda-utils/__tests__/sqs.test.ts @@ -0,0 +1,35 @@ +import { readSqsStringAttribute } from '../sqs'; + +describe('readSqsStringAttribute', () => { + it('returns the string value when the attribute exists and has String dataType', () => { + const record = { + messageAttributes: { + correlationId: { dataType: 'String', stringValue: 'abc-123' }, + }, + }; + expect(readSqsStringAttribute(record, 'correlationId')).toBe('abc-123'); + }); + + it('returns undefined when the attribute does not exist', () => { + const record = { messageAttributes: {} }; + expect(readSqsStringAttribute(record, 'correlationId')).toBeUndefined(); + }); + + it('returns undefined when the attribute has a non-String dataType', () => { + const record = { + messageAttributes: { + correlationId: { dataType: 'Number', stringValue: '123' }, + }, + }; + expect(readSqsStringAttribute(record, 'correlationId')).toBeUndefined(); + }); + + it('returns undefined when the attribute has no stringValue', () => { + const record = { + messageAttributes: { + correlationId: { dataType: 'String' }, + }, + }; + expect(readSqsStringAttribute(record, 'correlationId')).toBeUndefined(); + }); +}); diff --git a/packages/shared-utils/src/lambda-utils/format-zod-issues.ts b/packages/shared-utils/src/lambda-utils/format-zod-issues.ts new file mode 100644 index 0000000..2b987af --- /dev/null +++ b/packages/shared-utils/src/lambda-utils/format-zod-issues.ts @@ -0,0 +1,20 @@ +/** + * Minimal structural shape of a Zod issue. Declared locally so the formatter + * stays dependency-free and does not couple the package to a specific Zod + * version; a `ZodError.issues` array is structurally assignable to this type. + */ +export interface FormattableZodIssue { + path: PropertyKey[]; + message: string; +} + +export function formatZodIssues( + issues: readonly FormattableZodIssue[], +): string { + return issues + .map((issue) => { + const path = issue.path.map(String).join('.'); + return path ? `${path}: ${issue.message}` : issue.message; + }) + .join('; '); +} diff --git a/packages/shared-utils/src/lambda-utils/index.ts b/packages/shared-utils/src/lambda-utils/index.ts new file mode 100644 index 0000000..09efe6d --- /dev/null +++ b/packages/shared-utils/src/lambda-utils/index.ts @@ -0,0 +1,5 @@ +export { MissingEnvironmentVariableError, requireEnv } from './require-env'; +export { formatZodIssues } from './format-zod-issues'; +export type { FormattableZodIssue } from './format-zod-issues'; +export { CORRELATION_ID_ATTRIBUTE, readSqsStringAttribute } from './sqs'; +export type { SqsMessageAttributeLike, SqsRecordLike } from './sqs'; diff --git a/packages/shared-utils/src/lambda-utils/require-env.ts b/packages/shared-utils/src/lambda-utils/require-env.ts new file mode 100644 index 0000000..2e3b47d --- /dev/null +++ b/packages/shared-utils/src/lambda-utils/require-env.ts @@ -0,0 +1,15 @@ +export class MissingEnvironmentVariableError extends Error { + constructor(name: string) { + super(`${name} is required`); + this.name = 'MissingEnvironmentVariableError'; + } +} + +export function requireEnv(name: string): string { + // eslint-disable-next-line security/detect-object-injection -- name is always a controlled string literal at call sites + const value = process.env[name]; + if (!value) { + throw new MissingEnvironmentVariableError(name); + } + return value; +} diff --git a/packages/shared-utils/src/lambda-utils/sqs.ts b/packages/shared-utils/src/lambda-utils/sqs.ts new file mode 100644 index 0000000..a567c67 --- /dev/null +++ b/packages/shared-utils/src/lambda-utils/sqs.ts @@ -0,0 +1,20 @@ +export const CORRELATION_ID_ATTRIBUTE = 'correlationId' as const; + +export interface SqsMessageAttributeLike { + dataType?: string; + stringValue?: string; +} + +export interface SqsRecordLike { + messageAttributes: Record; +} + +export function readSqsStringAttribute( + record: SqsRecordLike, + attributeName: string, +): string | undefined { + // eslint-disable-next-line security/detect-object-injection -- attributeName is always a controlled string literal at call sites + const attribute = record.messageAttributes[attributeName]; + if (attribute?.dataType !== 'String') return undefined; + return attribute.stringValue; +} diff --git a/packages/shared-utils/src/logger/README.md b/packages/shared-utils/src/logger/README.md new file mode 100644 index 0000000..d1abf68 --- /dev/null +++ b/packages/shared-utils/src/logger/README.md @@ -0,0 +1,64 @@ +# `@nhsdigital/nhs-notify-shared-utils/logger` + +A generic [pino](https://getpino.io)-backed `Logger`, with support for opt-in log redaction. + +## Import + +```ts +import { Logger } from "@nhsdigital/nhs-notify-shared-utils/logger"; +import type { + LogContext, + LoggerOptions, +} from "@nhsdigital/nhs-notify-shared-utils/logger"; +``` + +`pino` is a peer dependency; the consumer installs it. + +## Usage + +```ts +const logger = new Logger(); + +logger.info("Handler started"); +logger.error("Processing failed", { error: caughtError }); +``` + +### Log context + +`addContext` merges fields into every later log line. `correlationId` returns the +bound correlation id when one is set. + +```ts +logger.addContext({ correlationId: "abc-123" }); +logger.info("Message received"); // includes correlationId +logger.correlationId; // 'abc-123' +logger.clearContext(); +``` + +### Initial context + +```ts +const logger = new Logger({ initialContext: { correlationId: "abc-123" } }); +``` + +### Redaction (opt in) + +No paths are redacted unless the caller supplies them. Pass the paths the +bounded context needs; the format is [pino redaction paths](https://getpino.io/#/docs/redaction). + +```ts +const logger = new Logger({ + redactPaths: ["req.headers.authorization", "*.password"], +}); +``` + +## Options + +| Option | Type | Default | Purpose | +| ---------------- | ------------ | ------- | ---------------------------------- | +| `initialContext` | `LogContext` | `{}` | Context bound at construction. | +| `redactPaths` | `string[]` | `[]` | Paths to redact. Empty means none. | + +## Log level + +The level is read from `process.env.LOG_LEVEL` (default `info`). diff --git a/packages/shared-utils/src/logger/__tests__/logger.test.ts b/packages/shared-utils/src/logger/__tests__/logger.test.ts new file mode 100644 index 0000000..456f37c --- /dev/null +++ b/packages/shared-utils/src/logger/__tests__/logger.test.ts @@ -0,0 +1,198 @@ +import pino from 'pino'; +import { LogContext, Logger } from '..'; + +jest.mock('pino', () => { + const info = jest.fn(); + const error = jest.fn(); + const warn = jest.fn(); + const debug = jest.fn(); + const child = jest.fn(); + const mockPino = jest.fn(() => ({ info, error, warn, debug, child })); + Object.defineProperty(mockPino, 'destination', { + value: jest.fn(() => ({})), + }); + return { + __esModule: true, + default: mockPino, + info, + error, + warn, + debug, + child, + }; +}); + +const mockLoggerMethods = pino() as jest.Mocked>; + +type PinoConfig = { + formatters: { level: (label: string) => { level: string } }; + timestamp: () => string; + redact?: string[]; +}; + +const pinoMock = pino as unknown as jest.Mock; + +const lastPinoConfig = (): PinoConfig => + pinoMock.mock.calls.at(-1)[0] as PinoConfig; + +describe('Logger', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockLoggerMethods.child.mockReturnValue(mockLoggerMethods); + }); + + describe('constructor', () => { + it('creates a logger without initial context', () => { + const testLogger = new Logger(); + expect(testLogger).toBeInstanceOf(Logger); + expect(mockLoggerMethods.child).not.toHaveBeenCalled(); + }); + + it('creates a logger with initial context', () => { + const initialContext: LogContext = { correlationId: 'corr-123' }; + const testLogger = new Logger({ initialContext }); + expect(testLogger).toBeInstanceOf(Logger); + expect(mockLoggerMethods.child).toHaveBeenCalledWith(initialContext); + }); + + it('does not configure redaction by default', () => { + const testLogger = new Logger(); + expect(testLogger).toBeInstanceOf(Logger); + expect(lastPinoConfig().redact).toBeUndefined(); + }); + + it('configures the redact paths supplied by the caller', () => { + const testLogger = new Logger({ + redactPaths: ['secret', '*.token'], + }); + expect(testLogger).toBeInstanceOf(Logger); + expect(lastPinoConfig().redact).toEqual(['secret', '*.token']); + }); + }); + + describe('addContext', () => { + it('adds new context to the logger', () => { + const testLogger = new Logger(); + testLogger.addContext({ correlationId: 'corr-789' }); + expect(mockLoggerMethods.child).toHaveBeenCalledWith({ + correlationId: 'corr-789', + }); + }); + + it('merges new context with existing context', () => { + const testLogger = new Logger({ + initialContext: { correlationId: 'corr-123' }, + }); + mockLoggerMethods.child.mockClear(); + testLogger.addContext({ messageId: 'msg-101' }); + expect(mockLoggerMethods.child).toHaveBeenCalledWith({ + correlationId: 'corr-123', + messageId: 'msg-101', + }); + }); + }); + + describe('clearContext', () => { + it('clears all context from the logger', () => { + const testLogger = new Logger({ + initialContext: { correlationId: 'corr-123' }, + }); + testLogger.clearContext(); + expect(testLogger.correlationId).toBeUndefined(); + }); + }); + + describe('correlationId accessor', () => { + it('returns undefined when no correlation id is bound', () => { + expect(new Logger().correlationId).toBeUndefined(); + }); + + it('returns the correlation id when bound via addContext', () => { + const testLogger = new Logger(); + testLogger.addContext({ correlationId: 'corr-abc' }); + expect(testLogger.correlationId).toBe('corr-abc'); + }); + + it('returns undefined when correlation id is not a string', () => { + const tainted = new Logger({ + initialContext: { correlationId: 123 as unknown as string }, + }); + expect(tainted.correlationId).toBeUndefined(); + }); + }); + + describe('log methods', () => { + it('logs info without and with additional context', () => { + const testLogger = new Logger(); + testLogger.info('info message'); + expect(mockLoggerMethods.info).toHaveBeenCalledWith({}, 'info message'); + const context: LogContext = { correlationId: 'corr-123' }; + testLogger.info('info message', context); + expect(mockLoggerMethods.info).toHaveBeenCalledWith( + context, + 'info message', + ); + }); + + it('logs warn without and with additional context', () => { + const testLogger = new Logger(); + testLogger.warn('warn message'); + expect(mockLoggerMethods.warn).toHaveBeenCalledWith({}, 'warn message'); + const context: LogContext = { correlationId: 'corr-456' }; + testLogger.warn('warn message', context); + expect(mockLoggerMethods.warn).toHaveBeenCalledWith( + context, + 'warn message', + ); + }); + + it('logs error without and with additional context', () => { + const testLogger = new Logger(); + testLogger.error('error message'); + expect(mockLoggerMethods.error).toHaveBeenCalledWith({}, 'error message'); + const context: LogContext = { error: new Error('fail') }; + testLogger.error('error message', context); + expect(mockLoggerMethods.error).toHaveBeenCalledWith( + context, + 'error message', + ); + }); + + it('logs debug without and with additional context', () => { + const testLogger = new Logger(); + testLogger.debug('debug message'); + expect(mockLoggerMethods.debug).toHaveBeenCalledWith({}, 'debug message'); + const context: LogContext = { correlationId: 'corr-101' }; + testLogger.debug('debug message', context); + expect(mockLoggerMethods.debug).toHaveBeenCalledWith( + context, + 'debug message', + ); + }); + }); +}); + +describe('pino configuration', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('level formatter uppercases the label', () => { + const testLogger = new Logger(); + expect(testLogger).toBeInstanceOf(Logger); + expect(lastPinoConfig().formatters.level('info')).toEqual({ + level: 'INFO', + }); + expect(lastPinoConfig().formatters.level('error')).toEqual({ + level: 'ERROR', + }); + }); + + it('timestamp returns a JSON fragment with an ISO timestamp', () => { + const testLogger = new Logger(); + expect(testLogger).toBeInstanceOf(Logger); + expect(lastPinoConfig().timestamp()).toMatch( + /^,"timestamp":"\d{4}-\d{2}-\d{2}T/, + ); + }); +}); diff --git a/packages/shared-utils/src/logger/index.ts b/packages/shared-utils/src/logger/index.ts new file mode 100644 index 0000000..81b9be9 --- /dev/null +++ b/packages/shared-utils/src/logger/index.ts @@ -0,0 +1,2 @@ +export { Logger } from './logger'; +export type { LogContext, LoggerOptions } from './logger'; diff --git a/packages/shared-utils/src/logger/logger.ts b/packages/shared-utils/src/logger/logger.ts new file mode 100644 index 0000000..53fa9d5 --- /dev/null +++ b/packages/shared-utils/src/logger/logger.ts @@ -0,0 +1,79 @@ +import pino from 'pino'; + +export interface LogContext { + correlationId?: string; + error?: Error | string; + + [key: string]: unknown; +} + +export interface LoggerOptions { + initialContext?: LogContext; + redactPaths?: string[]; +} + +const resolveLogLevel = (level = 'info'): string => level; + +function createBasePinoLogger(redactPaths: string[]): pino.Logger { + return pino( + { + level: resolveLogLevel(process.env.LOG_LEVEL), + formatters: { + level: (label: string) => ({ level: label.toUpperCase() }), + }, + timestamp: () => `,"timestamp":"${new Date().toISOString()}"`, + ...(redactPaths.length > 0 ? { redact: redactPaths } : {}), + }, + pino.destination({ sync: true }), + ); +} + +export class Logger { + private readonly rootPinoLogger: pino.Logger; + + private pinoLogger: pino.Logger; + + protected context: LogContext = {}; + + constructor(options: LoggerOptions = {}) { + const { initialContext, redactPaths = [] } = options; + this.rootPinoLogger = createBasePinoLogger(redactPaths); + if (initialContext) { + this.context = { ...initialContext }; + this.pinoLogger = this.rootPinoLogger.child(initialContext); + } else { + this.pinoLogger = this.rootPinoLogger; + } + } + + addContext(context: LogContext): void { + this.context = { ...this.context, ...context }; + this.pinoLogger = this.rootPinoLogger.child(this.context); + } + + clearContext(): void { + this.context = {}; + this.pinoLogger = this.rootPinoLogger; + } + + get correlationId(): string | undefined { + const value = this.context.correlationId; + return typeof value === 'string' ? value : undefined; + } + + info(message: string, additionalContext?: LogContext): void { + this.pinoLogger.info(additionalContext ?? {}, message); + } + + warn(message: string, additionalContext?: LogContext): void { + this.pinoLogger.warn(additionalContext ?? {}, message); + } + + error(message: string, additionalContext?: LogContext): void { + this.pinoLogger.error(additionalContext ?? {}, message); + } + + debug(message: string, additionalContext?: LogContext): void { + this.pinoLogger.debug(additionalContext ?? {}, message); + } +} diff --git a/packages/shared-utils/src/s3-json/README.md b/packages/shared-utils/src/s3-json/README.md new file mode 100644 index 0000000..e4ed646 --- /dev/null +++ b/packages/shared-utils/src/s3-json/README.md @@ -0,0 +1,52 @@ +# `@nhsdigital/nhs-notify-shared-utils/s3-json` + +Fetch a JSON object from S3, with optional validation. Missing keys resolve to +`undefined` instead of throwing. + +## Import + +```ts +import { getJsonObject } from "@nhsdigital/nhs-notify-shared-utils/s3-json"; +import type { + GetJsonObjectParams, + JsonValidator, +} from "@nhsdigital/nhs-notify-shared-utils/s3-json"; +``` + +`@aws-sdk/client-s3` is a peer dependency; the consumer installs it and passes a +client in. + +## Usage + +```ts +import { S3Client } from "@aws-sdk/client-s3"; + +const s3 = new S3Client({ region: "eu-west-2" }); + +const config = await getJsonObject(s3, { + bucket: "my-bucket", + key: "config.json", +}); +// `config` is `unknown`, or `undefined` when the key does not exist. +``` + +### With validation + +Pass any object with a `parse(data): T` method (e.g. a Zod schema). The resolved value is typed as `T`. + +```ts +const config = await getJsonObject(s3, { + bucket: "my-bucket", + key: "config.json", + validator: configSchema, +}); +``` + +## Behaviour + +- Returns `undefined` when the key does not exist (`NoSuchKey`, or an `Error` + whose `name` is `NoSuchKey`). +- Returns `undefined` when the object has no body. +- Any other error is rethrown. +- With a validator, the parsed JSON is passed through `validator.parse`; a + validation failure throws. diff --git a/packages/shared-utils/src/s3-json/__tests__/s3-json.test.ts b/packages/shared-utils/src/s3-json/__tests__/s3-json.test.ts new file mode 100644 index 0000000..7333054 --- /dev/null +++ b/packages/shared-utils/src/s3-json/__tests__/s3-json.test.ts @@ -0,0 +1,101 @@ +import { GetObjectCommand, NoSuchKey, type S3Client } from '@aws-sdk/client-s3'; +import { getJsonObject } from '../s3-json'; + +jest.mock('@aws-sdk/client-s3', () => { + class MockNoSuchKey extends Error { + constructor() { + super('missing'); + this.name = 'NoSuchKey'; + } + } + return { + __esModule: true, + GetObjectCommand: jest.fn((input) => ({ input })), + NoSuchKey: MockNoSuchKey, + S3Client: jest.fn(), + }; +}); + +function buildS3Client(send: jest.Mock): S3Client { + return { send } as unknown as S3Client; +} + +function bodyResolving(value: string | undefined) { + return { Body: { transformToString: jest.fn().mockResolvedValue(value) } }; +} + +describe('getJsonObject', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('sends a GetObjectCommand with the supplied bucket and key', async () => { + const send = jest.fn().mockResolvedValue(bodyResolving('{"a":1}')); + await getJsonObject(buildS3Client(send), { bucket: 'b', key: 'k.json' }); + expect(GetObjectCommand).toHaveBeenCalledWith({ + Bucket: 'b', + Key: 'k.json', + }); + expect(send).toHaveBeenCalledTimes(1); + }); + + it('returns the parsed value when no validator is supplied', async () => { + const send = jest.fn().mockResolvedValue(bodyResolving('{"a":1}')); + await expect( + getJsonObject(buildS3Client(send), { bucket: 'b', key: 'k.json' }), + ).resolves.toEqual({ a: 1 }); + }); + + it('returns the validated value when a validator is supplied', async () => { + const send = jest.fn().mockResolvedValue(bodyResolving('{"a":1}')); + const validator = { + parse: jest.fn((data) => ({ ...(data as object), b: 2 })), + }; + await expect( + getJsonObject(buildS3Client(send), { + bucket: 'b', + key: 'k.json', + validator, + }), + ).resolves.toEqual({ a: 1, b: 2 }); + expect(validator.parse).toHaveBeenCalledWith({ a: 1 }); + }); + + it('returns undefined when the object body is absent', async () => { + const send = jest.fn().mockResolvedValue({ Body: undefined }); + await expect( + getJsonObject(buildS3Client(send), { bucket: 'b', key: 'k.json' }), + ).resolves.toBeUndefined(); + }); + + it('returns undefined when the transformed body is undefined', async () => { + const send = jest.fn().mockResolvedValue(bodyResolving(undefined)); + await expect( + getJsonObject(buildS3Client(send), { bucket: 'b', key: 'k.json' }), + ).resolves.toBeUndefined(); + }); + + it('returns undefined when the key does not exist (NoSuchKey instance)', async () => { + const send = jest + .fn() + .mockRejectedValue(new NoSuchKey({ $metadata: {}, message: 'missing' })); + await expect( + getJsonObject(buildS3Client(send), { bucket: 'b', key: 'k.json' }), + ).resolves.toBeUndefined(); + }); + + it('returns undefined for an Error whose name is NoSuchKey', async () => { + const error = Object.assign(new Error('missing'), { name: 'NoSuchKey' }); + const send = jest.fn().mockRejectedValue(error); + await expect( + getJsonObject(buildS3Client(send), { bucket: 'b', key: 'k.json' }), + ).resolves.toBeUndefined(); + }); + + it('rethrows any other error', async () => { + const send = jest.fn().mockRejectedValue(new Error('access denied')); + await expect( + getJsonObject(buildS3Client(send), { bucket: 'b', key: 'k.json' }), + ).rejects.toThrow('access denied'); + }); +}); diff --git a/packages/shared-utils/src/s3-json/index.ts b/packages/shared-utils/src/s3-json/index.ts new file mode 100644 index 0000000..2a0b489 --- /dev/null +++ b/packages/shared-utils/src/s3-json/index.ts @@ -0,0 +1,2 @@ +export { getJsonObject } from './s3-json'; +export type { GetJsonObjectParams, JsonValidator } from './s3-json'; diff --git a/packages/shared-utils/src/s3-json/s3-json.ts b/packages/shared-utils/src/s3-json/s3-json.ts new file mode 100644 index 0000000..6d4d439 --- /dev/null +++ b/packages/shared-utils/src/s3-json/s3-json.ts @@ -0,0 +1,49 @@ +import { GetObjectCommand, NoSuchKey, type S3Client } from '@aws-sdk/client-s3'; + +/** + * Structural validator shape. A Zod schema satisfies this, so callers can pass + * `schema` directly without this package depending on Zod. + */ +export interface JsonValidator { + parse: (data: unknown) => T; +} + +export interface GetJsonObjectParams { + bucket: string; + key: string; + validator?: JsonValidator; +} + +function isNoSuchKey(error: unknown): boolean { + return ( + error instanceof NoSuchKey || + (error instanceof Error && error.name === 'NoSuchKey') + ); +} + +/** + * Fetches a JSON object from S3, returning `undefined` when the key does not + * exist. When a validator is supplied the parsed value is validated (and typed) + * through it; otherwise the raw parsed value is returned. + */ +export async function getJsonObject( + s3Client: S3Client, + { bucket, key, validator }: GetJsonObjectParams, +): Promise { + try { + const response = await s3Client.send( + new GetObjectCommand({ Bucket: bucket, Key: key }), + ); + const body = await response.Body?.transformToString(); + if (body === undefined) { + return undefined; + } + const parsed: unknown = JSON.parse(body); + return validator ? validator.parse(parsed) : (parsed as T); + } catch (error) { + if (isNoSuchKey(error)) { + return undefined; + } + throw error; + } +} diff --git a/packages/shared-utils/src/test-support/README.md b/packages/shared-utils/src/test-support/README.md new file mode 100644 index 0000000..d05956f --- /dev/null +++ b/packages/shared-utils/src/test-support/README.md @@ -0,0 +1,81 @@ +# `@nhsdigital/nhs-notify-shared-utils/test-support` + +Helpers for integration tests: deployment/naming helpers, polling primitives, an +override-based event-factory base, and per-service AWS client factories. + +## Subpath layout + +The AWS client factories and service helpers are split by service so that +importing one service does **not** load the others' AWS SDK packages. The AWS +SDK clients are optional peer dependencies, so a consumer installs only the ones +it uses. + +| Subpath | AWS SDK package | Exports | +| ------------------------------ | ---------------------------------- | ------------------------------------------------------------------------------------------- | +| `./test-support` | none | `getDeploymentDetails`, `buildLambdaLogGroupName`, `pollUntil`, `safeJsonParse`, `applyOverrides`, `applyEventOverrides`, plus types | +| `./test-support/cloudwatch` | `@aws-sdk/client-cloudwatch-logs` | `createCloudWatchLogsClient`, `awaitMatchingLogEntries`, `queryLogEntries` | +| `./test-support/sqs` | `@aws-sdk/client-sqs` | `createSqsClient`, `buildQueueUrl`, `sendSqsEvent`, `awaitMessageMatching`, `purgeQueue`, `purgeQueues` | +| `./test-support/s3` | `@aws-sdk/client-s3` | `createS3Client` | +| `./test-support/dynamodb` | `@aws-sdk/client-dynamodb`, `@aws-sdk/lib-dynamodb` | `createDynamoDbDocumentClient` | +| `./test-support/eventbridge` | `@aws-sdk/client-eventbridge` | `createEventBridgeClient` | + +The `./test-support` barrel is AWS-SDK-free, so it is always safe to import. + +## Usage + +Import the SDK-free helpers: + +```ts +import { + getDeploymentDetails, + buildLambdaLogGroupName, + pollUntil, +} from '@nhsdigital/nhs-notify-shared-utils/test-support'; + +const deployment = getDeploymentDetails({ + region: 'eu-west-2', + project: 'nhs', + component: 'ar', +}); +const logGroup = buildLambdaLogGroupName(deployment, 'my-function'); +``` + +Import each service's client factory and helpers individually: + +```ts +import { + createCloudWatchLogsClient, + awaitMatchingLogEntries, +} from '@nhsdigital/nhs-notify-shared-utils/test-support/cloudwatch'; +import { + createSqsClient, + awaitMessageMatching, +} from '@nhsdigital/nhs-notify-shared-utils/test-support/sqs'; + +const logs = createCloudWatchLogsClient(deployment); +const sqs = createSqsClient(deployment); +``` + +## Polling + +`pollUntil` retries an async check until it returns `true`, or throws +`PollTimeoutError` once the timeout elapses. `now` and `wait` are injectable to +keep unit tests deterministic. + +```ts +await pollUntil( + async () => (await countRows()) >= 1, + 'at least one row written', + { timeoutMs: 30_000, intervalMs: 500 }, +); +``` + +## Event factories + +`applyOverrides` and `applyEventOverrides` build fixtures from a base plus +overrides. Domain-specific factories are built on top of these in each bounded +context. + +```ts +const event = applyEventOverrides(baseEvent, { data: { messageId: 'm-1' } }); +``` diff --git a/packages/shared-utils/src/test-support/__tests__/cloudwatch.test.ts b/packages/shared-utils/src/test-support/__tests__/cloudwatch.test.ts new file mode 100644 index 0000000..cbf6738 --- /dev/null +++ b/packages/shared-utils/src/test-support/__tests__/cloudwatch.test.ts @@ -0,0 +1,151 @@ +import { + CloudWatchLogsClient, + FilterLogEventsCommand, + ThrottlingException, +} from '@aws-sdk/client-cloudwatch-logs'; +import { + awaitMatchingLogEntries, + createCloudWatchLogsClient, + queryLogEntries, +} from '../cloudwatch'; + +jest.mock('@aws-sdk/client-cloudwatch-logs', () => { + class MockThrottlingException extends Error { + constructor() { + super('throttled'); + this.name = 'ThrottlingException'; + } + } + return { + CloudWatchLogsClient: jest.fn(), + FilterLogEventsCommand: jest.fn((input) => ({ _type: 'Filter', input })), + ThrottlingException: MockThrottlingException, + }; +}); + +function client(send: jest.Mock): CloudWatchLogsClient { + return { send } as unknown as CloudWatchLogsClient; +} + +const pollControl = () => { + let clock = 0; + return { + now: jest.fn(() => clock), + wait: jest.fn().mockImplementation(() => { + clock += 1000; + return Promise.resolve(); + }), + }; +}; + +describe('createCloudWatchLogsClient', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('creates a CloudWatch Logs client for the region', () => { + createCloudWatchLogsClient({ region: 'eu-west-2' }); + expect(CloudWatchLogsClient).toHaveBeenCalledWith({ region: 'eu-west-2' }); + }); +}); + +describe('queryLogEntries', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('returns entries with a message, dropping empty ones', async () => { + const send = jest.fn().mockResolvedValue({ + events: [{ message: 'a' }, { message: '' }, {}, { message: 'b' }], + }); + await expect( + queryLogEntries(client(send), 'group', 'pattern', 1000), + ).resolves.toEqual([{ message: 'a' }, { message: 'b' }]); + }); + + it('returns an empty array when there are no events', async () => { + const send = jest.fn().mockResolvedValue({}); + await expect( + queryLogEntries(client(send), 'group', 'pattern', 1000), + ).resolves.toEqual([]); + }); + + it('applies the lookback window, clamping to zero', async () => { + const send = jest.fn().mockResolvedValue({ events: [] }); + await queryLogEntries(client(send), 'group', 'pattern', 1000, 5000); + expect(FilterLogEventsCommand).toHaveBeenCalledWith({ + logGroupName: 'group', + startTime: 0, + filterPattern: 'pattern', + }); + }); +}); + +describe('awaitMatchingLogEntries', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('returns matched entries once the minimum count is reached', async () => { + const send = jest.fn().mockResolvedValue({ events: [{ message: 'a' }] }); + await expect( + awaitMatchingLogEntries(client(send), 'group', 'pattern', 1000), + ).resolves.toEqual([{ message: 'a' }]); + }); + + it('waits until enough entries match the minimum count', async () => { + const send = jest + .fn() + .mockResolvedValueOnce({ events: [{ message: 'a' }] }) + .mockResolvedValueOnce({ + events: [{ message: 'a' }, { message: 'b' }], + }); + const { now, wait } = pollControl(); + await expect( + awaitMatchingLogEntries(client(send), 'group', 'pattern', 1000, { + minCount: 2, + lookbackMs: 100, + now, + wait, + timeoutMs: 10_000, + }), + ).resolves.toEqual([{ message: 'a' }, { message: 'b' }]); + }); + + it('retries when CloudWatch throttles', async () => { + const send = jest + .fn() + .mockRejectedValueOnce( + new ThrottlingException({ $metadata: {}, message: 'throttled' }), + ) + .mockResolvedValueOnce({ events: [{ message: 'a' }] }); + const { now, wait } = pollControl(); + await expect( + awaitMatchingLogEntries(client(send), 'group', 'pattern', 1000, { + now, + wait, + timeoutMs: 10_000, + }), + ).resolves.toEqual([{ message: 'a' }]); + }); + + it('rethrows a non-throttling error', async () => { + const send = jest.fn().mockRejectedValue(new Error('boom')); + await expect( + awaitMatchingLogEntries(client(send), 'group', 'pattern', 1000), + ).rejects.toThrow('boom'); + }); + + it('returns whatever matched when the poll times out', async () => { + const send = jest.fn().mockResolvedValue({ events: [{ message: 'a' }] }); + const { now, wait } = pollControl(); + await expect( + awaitMatchingLogEntries(client(send), 'group', 'pattern', 1000, { + minCount: 2, + now, + wait, + timeoutMs: 500, + }), + ).resolves.toEqual([{ message: 'a' }]); + }); +}); diff --git a/packages/shared-utils/src/test-support/__tests__/deployment.test.ts b/packages/shared-utils/src/test-support/__tests__/deployment.test.ts new file mode 100644 index 0000000..2e255b2 --- /dev/null +++ b/packages/shared-utils/src/test-support/__tests__/deployment.test.ts @@ -0,0 +1,112 @@ +import { buildLambdaLogGroupName, getDeploymentDetails } from '../deployment'; + +describe('getDeploymentDetails', () => { + const ORIGINAL_ENV = { ...process.env }; + + afterEach(() => { + process.env = { ...ORIGINAL_ENV }; + }); + + it('reads values from the environment', () => { + process.env.AWS_REGION = 'eu-west-1'; + process.env.ENVIRONMENT = 'dev'; + process.env.PROJECT = 'proj'; + process.env.COMPONENT = 'comp'; + process.env.AWS_ACCOUNT_ID = '123456789012'; + + expect(getDeploymentDetails()).toEqual({ + region: 'eu-west-1', + environment: 'dev', + project: 'proj', + component: 'comp', + accountId: '123456789012', + }); + }); + + it('applies passed-in defaults for region, project and component', () => { + delete process.env.AWS_REGION; + delete process.env.PROJECT; + delete process.env.COMPONENT; + process.env.ENVIRONMENT = 'dev'; + process.env.AWS_ACCOUNT_ID = '123456789012'; + + expect( + getDeploymentDetails({ + region: 'eu-west-2', + project: 'nhs', + component: 'ar', + }), + ).toEqual({ + region: 'eu-west-2', + environment: 'dev', + project: 'nhs', + component: 'ar', + accountId: '123456789012', + }); + }); + + it('throws when AWS_REGION is missing and no default is provided', () => { + delete process.env.AWS_REGION; + process.env.ENVIRONMENT = 'dev'; + process.env.PROJECT = 'nhs'; + process.env.COMPONENT = 'comp'; + process.env.AWS_ACCOUNT_ID = '123456789012'; + expect(() => getDeploymentDetails()).toThrow( + 'AWS_REGION environment variable must be set or a default provided', + ); + }); + + it('throws when ENVIRONMENT is missing', () => { + process.env.AWS_REGION = 'eu-west-2'; + delete process.env.ENVIRONMENT; + process.env.COMPONENT = 'comp'; + process.env.AWS_ACCOUNT_ID = '123456789012'; + expect(() => getDeploymentDetails()).toThrow( + 'ENVIRONMENT environment variable must be set', + ); + }); + + it('throws when PROJECT is missing and no default is provided', () => { + process.env.AWS_REGION = 'eu-west-2'; + process.env.ENVIRONMENT = 'dev'; + delete process.env.PROJECT; + process.env.COMPONENT = 'comp'; + process.env.AWS_ACCOUNT_ID = '123456789012'; + expect(() => getDeploymentDetails()).toThrow( + 'PROJECT environment variable must be set or a default provided', + ); + }); + + it('throws when COMPONENT is missing and no default is provided', () => { + process.env.AWS_REGION = 'eu-west-2'; + process.env.ENVIRONMENT = 'dev'; + process.env.PROJECT = 'nhs'; + delete process.env.COMPONENT; + process.env.AWS_ACCOUNT_ID = '123456789012'; + expect(() => getDeploymentDetails()).toThrow( + 'COMPONENT environment variable must be set or a default provided', + ); + }); + + it('throws when AWS_ACCOUNT_ID is missing', () => { + process.env.AWS_REGION = 'eu-west-2'; + process.env.ENVIRONMENT = 'dev'; + process.env.PROJECT = 'nhs'; + process.env.COMPONENT = 'comp'; + delete process.env.AWS_ACCOUNT_ID; + expect(() => getDeploymentDetails()).toThrow( + 'AWS_ACCOUNT_ID environment variable must be set', + ); + }); +}); + +describe('buildLambdaLogGroupName', () => { + it('builds the log group name from the deployment components', () => { + expect( + buildLambdaLogGroupName( + { component: 'ar', environment: 'dev', project: 'nhs' }, + 'my-fn', + ), + ).toBe('/aws/lambda/nhs-dev-ar-my-fn'); + }); +}); diff --git a/packages/shared-utils/src/test-support/__tests__/dynamodb.test.ts b/packages/shared-utils/src/test-support/__tests__/dynamodb.test.ts new file mode 100644 index 0000000..24f5567 --- /dev/null +++ b/packages/shared-utils/src/test-support/__tests__/dynamodb.test.ts @@ -0,0 +1,26 @@ +import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; +import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb'; +import { createDynamoDbDocumentClient } from '../dynamodb'; + +jest.mock('@aws-sdk/client-dynamodb', () => ({ DynamoDBClient: jest.fn() })); +jest.mock('@aws-sdk/lib-dynamodb', () => ({ + DynamoDBDocumentClient: { from: jest.fn(() => ({ documentClient: true })) }, +})); + +describe('createDynamoDbDocumentClient', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('creates a DynamoDB document client that removes undefined values', () => { + const result = createDynamoDbDocumentClient({ region: 'eu-west-2' }); + expect(DynamoDBClient).toHaveBeenCalledWith({ region: 'eu-west-2' }); + expect(DynamoDBDocumentClient.from).toHaveBeenCalledWith( + expect.anything(), + { + marshallOptions: { removeUndefinedValues: true }, + }, + ); + expect(result).toEqual({ documentClient: true }); + }); +}); diff --git a/packages/shared-utils/src/test-support/__tests__/event-factory.test.ts b/packages/shared-utils/src/test-support/__tests__/event-factory.test.ts new file mode 100644 index 0000000..d016e56 --- /dev/null +++ b/packages/shared-utils/src/test-support/__tests__/event-factory.test.ts @@ -0,0 +1,28 @@ +import { applyEventOverrides, applyOverrides } from '../event-factory'; + +describe('applyOverrides', () => { + it('returns the base when no overrides are supplied', () => { + expect(applyOverrides({ a: 1, b: 2 })).toEqual({ a: 1, b: 2 }); + }); + + it('shallow-merges overrides over the base', () => { + expect(applyOverrides({ a: 1, b: 2 }, { b: 3 })).toEqual({ a: 1, b: 3 }); + }); +}); + +describe('applyEventOverrides', () => { + const base = { id: 'e1', type: 't', data: { clientId: 'c1', value: 1 } }; + + it('returns the base when no overrides are supplied', () => { + expect(applyEventOverrides(base)).toEqual(base); + }); + + it('merges event-level and data-level overrides', () => { + expect( + applyEventOverrides(base, { + event: { type: 't2' }, + data: { value: 2 }, + }), + ).toEqual({ id: 'e1', type: 't2', data: { clientId: 'c1', value: 2 } }); + }); +}); diff --git a/packages/shared-utils/src/test-support/__tests__/eventbridge.test.ts b/packages/shared-utils/src/test-support/__tests__/eventbridge.test.ts new file mode 100644 index 0000000..85d0ea6 --- /dev/null +++ b/packages/shared-utils/src/test-support/__tests__/eventbridge.test.ts @@ -0,0 +1,17 @@ +import { EventBridgeClient } from '@aws-sdk/client-eventbridge'; +import { createEventBridgeClient } from '../eventbridge'; + +jest.mock('@aws-sdk/client-eventbridge', () => ({ + EventBridgeClient: jest.fn(), +})); + +describe('createEventBridgeClient', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('creates an EventBridge client for the region', () => { + createEventBridgeClient({ region: 'eu-west-2' }); + expect(EventBridgeClient).toHaveBeenCalledWith({ region: 'eu-west-2' }); + }); +}); diff --git a/packages/shared-utils/src/test-support/__tests__/poll.test.ts b/packages/shared-utils/src/test-support/__tests__/poll.test.ts new file mode 100644 index 0000000..28c8792 --- /dev/null +++ b/packages/shared-utils/src/test-support/__tests__/poll.test.ts @@ -0,0 +1,103 @@ +import { + DEFAULT_POLL_TIMEOUT_MS, + POLL_INTERVAL_MS, + PollTimeoutError, + delay, + pollUntil, + safeJsonParse, +} from '../poll'; + +describe('constants', () => { + it('exposes poll interval and default timeout', () => { + expect(POLL_INTERVAL_MS).toBe(500); + expect(DEFAULT_POLL_TIMEOUT_MS).toBe(60_000); + }); +}); + +describe('safeJsonParse', () => { + it('parses valid JSON', () => { + expect(safeJsonParse('{"a":1}')).toEqual({ a: 1 }); + }); + + it('returns undefined for invalid JSON', () => { + expect(safeJsonParse('{ not json')).toBeUndefined(); + }); +}); + +describe('delay', () => { + beforeEach(() => { + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + it('resolves after the given delay', async () => { + const resolved = jest.fn(); + const promise = delay(1000).then(resolved); + expect(resolved).not.toHaveBeenCalled(); + jest.advanceTimersByTime(1000); + await promise; + expect(resolved).toHaveBeenCalledTimes(1); + }); +}); + +describe('pollUntil', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('returns immediately when the first attempt succeeds, using default options', async () => { + const attempt = jest.fn().mockResolvedValue(true); + await pollUntil(attempt, 'thing'); + expect(attempt).toHaveBeenCalledTimes(1); + }); + + it('retries until the attempt succeeds', async () => { + const attempt = jest + .fn() + .mockResolvedValueOnce(false) + .mockResolvedValueOnce(false) + .mockResolvedValue(true); + let clock = 0; + const now = jest.fn(() => clock); + const advancingWait = jest.fn().mockImplementation(() => { + clock += 100; + return Promise.resolve(); + }); + + await pollUntil(attempt, 'thing', { + wait: advancingWait, + now, + timeoutMs: 10_000, + intervalMs: 100, + }); + + expect(attempt).toHaveBeenCalledTimes(3); + expect(advancingWait).toHaveBeenCalledTimes(2); + }); + + it('throws PollTimeoutError once the deadline passes', async () => { + const attempt = jest.fn().mockResolvedValue(false); + let clock = 0; + const now = jest.fn(() => clock); + const advancingWait = jest.fn().mockImplementation(() => { + clock += 1000; + return Promise.resolve(); + }); + + await expect( + pollUntil(attempt, 'thing', { + wait: advancingWait, + now, + timeoutMs: 500, + intervalMs: 100, + }), + ).rejects.toThrow(PollTimeoutError); + }); + + it('sets the error name on PollTimeoutError', () => { + expect(new PollTimeoutError('x').name).toBe('PollTimeoutError'); + }); +}); diff --git a/packages/shared-utils/src/test-support/__tests__/s3.test.ts b/packages/shared-utils/src/test-support/__tests__/s3.test.ts new file mode 100644 index 0000000..ca40e1d --- /dev/null +++ b/packages/shared-utils/src/test-support/__tests__/s3.test.ts @@ -0,0 +1,15 @@ +import { S3Client } from '@aws-sdk/client-s3'; +import { createS3Client } from '../s3'; + +jest.mock('@aws-sdk/client-s3', () => ({ S3Client: jest.fn() })); + +describe('createS3Client', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('creates an S3 client for the region', () => { + createS3Client({ region: 'eu-west-2' }); + expect(S3Client).toHaveBeenCalledWith({ region: 'eu-west-2' }); + }); +}); diff --git a/packages/shared-utils/src/test-support/__tests__/sqs.test.ts b/packages/shared-utils/src/test-support/__tests__/sqs.test.ts new file mode 100644 index 0000000..dc22b5d --- /dev/null +++ b/packages/shared-utils/src/test-support/__tests__/sqs.test.ts @@ -0,0 +1,260 @@ +import { + ChangeMessageVisibilityCommand, + PurgeQueueCommand, + ReceiveMessageCommand, + SQSClient, + SendMessageCommand, +} from '@aws-sdk/client-sqs'; +import type { DeploymentDetails } from '../deployment'; +import { + awaitMessageMatching, + buildQueueUrl, + createSqsClient, + purgeQueue, + purgeQueues, + sendSqsEvent, +} from '../sqs'; + +jest.mock('@aws-sdk/client-sqs', () => ({ + ChangeMessageVisibilityCommand: jest.fn((input) => ({ + _type: 'ChangeVisibility', + input, + })), + PurgeQueueCommand: jest.fn((input) => ({ _type: 'Purge', input })), + ReceiveMessageCommand: jest.fn((input) => ({ _type: 'Receive', input })), + SendMessageCommand: jest.fn((input) => ({ _type: 'Send', input })), + SQSClient: jest.fn(), +})); + +describe('createSqsClient', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('creates an SQS client for the region', () => { + createSqsClient({ region: 'eu-west-2' }); + expect(SQSClient).toHaveBeenCalledWith({ region: 'eu-west-2' }); + }); +}); + +const details: DeploymentDetails = { + region: 'eu-west-2', + environment: 'dev', + project: 'nhs', + component: 'ar', + accountId: '123456789012', +}; + +function client(send: jest.Mock): SQSClient { + return { send } as unknown as SQSClient; +} + +const pollControl = () => { + let clock = 0; + return { + now: jest.fn(() => clock), + wait: jest.fn().mockImplementation(() => { + clock += 100; + return Promise.resolve(); + }), + }; +}; + +describe('buildQueueUrl', () => { + it('builds a standard queue url with the queue suffix', () => { + expect(buildQueueUrl(details, 'inbound')).toBe( + 'https://sqs.eu-west-2.amazonaws.com/123456789012/nhs-dev-ar-inbound-queue', + ); + }); + + it('builds a FIFO queue url', () => { + expect(buildQueueUrl(details, 'inbound', { fifo: true })).toBe( + 'https://sqs.eu-west-2.amazonaws.com/123456789012/nhs-dev-ar-inbound-queue.fifo', + ); + }); + + it('omits the queue suffix when appendQueueSuffix is false', () => { + expect( + buildQueueUrl(details, 'raw-name', { appendQueueSuffix: false }), + ).toBe( + 'https://sqs.eu-west-2.amazonaws.com/123456789012/nhs-dev-ar-raw-name', + ); + }); +}); + +describe('sendSqsEvent', () => { + it('sends a message with the serialised event and no group id by default', async () => { + const send = jest.fn().mockResolvedValue({}); + await sendSqsEvent(client(send), 'queue-url', { id: 'e1' }); + expect(SendMessageCommand).toHaveBeenCalledWith({ + QueueUrl: 'queue-url', + MessageBody: JSON.stringify({ id: 'e1' }), + MessageGroupId: undefined, + MessageDeduplicationId: undefined, + }); + }); + + it('passes group and deduplication ids', async () => { + const send = jest.fn().mockResolvedValue({}); + await sendSqsEvent( + client(send), + 'queue-url', + { id: 'e1' }, + { + messageGroupId: 'g1', + messageDeduplicationId: 'd1', + }, + ); + expect(SendMessageCommand).toHaveBeenCalledWith({ + QueueUrl: 'queue-url', + MessageBody: JSON.stringify({ id: 'e1' }), + MessageGroupId: 'g1', + MessageDeduplicationId: 'd1', + }); + }); +}); + +describe('awaitMessageMatching', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('returns the first matching message', async () => { + const message = { Body: JSON.stringify({ match: true }) }; + const send = jest.fn().mockResolvedValue({ Messages: [message] }); + const result = await awaitMessageMatching( + client(send), + 'queue-url', + (body) => (body as { match?: boolean }).match === true, + 'a match', + ); + expect(result).toBe(message); + }); + + it('resets visibility on non-matching messages and retries', async () => { + const nonMatch = { + Body: JSON.stringify({ match: false }), + ReceiptHandle: 'rh-1', + }; + const match = { Body: JSON.stringify({ match: true }) }; + const send = jest + .fn() + .mockResolvedValueOnce({ Messages: [nonMatch] }) + .mockResolvedValueOnce({}) // ChangeMessageVisibility + .mockResolvedValueOnce({ Messages: [match] }); + const { now, wait } = pollControl(); + + const result = await awaitMessageMatching( + client(send), + 'queue-url', + (body) => (body as { match?: boolean }).match === true, + 'a match', + { now, wait, timeoutMs: 10_000 }, + ); + + expect(result).toBe(match); + expect(ChangeMessageVisibilityCommand).toHaveBeenCalledWith({ + QueueUrl: 'queue-url', + ReceiptHandle: 'rh-1', + VisibilityTimeout: 0, + }); + }); + + it('treats a malformed body and a message with no receipt handle as non-matching', async () => { + const malformed = { Body: '{ not json' }; + const empty = {}; + const match = { Body: JSON.stringify({ match: true }) }; + const send = jest + .fn() + .mockResolvedValueOnce({ Messages: [malformed, empty] }) + .mockResolvedValueOnce({ Messages: [match] }); + const { now, wait } = pollControl(); + + const result = await awaitMessageMatching( + client(send), + 'queue-url', + (body) => (body as { match?: boolean } | undefined)?.match === true, + 'a match', + { now, wait, timeoutMs: 10_000 }, + ); + + expect(result).toBe(match); + expect(ChangeMessageVisibilityCommand).not.toHaveBeenCalled(); + }); + + it('honours custom receive options', async () => { + const message = { Body: JSON.stringify({ match: true }) }; + const send = jest.fn().mockResolvedValue({ Messages: [message] }); + await awaitMessageMatching( + client(send), + 'queue-url', + () => true, + 'a match', + { + visibilityTimeoutSeconds: 45, + waitTimeSeconds: 2, + maxNumberOfMessages: 1, + }, + ); + expect(ReceiveMessageCommand).toHaveBeenCalledWith( + expect.objectContaining({ + VisibilityTimeout: 45, + WaitTimeSeconds: 2, + MaxNumberOfMessages: 1, + }), + ); + }); + + it('throws when no matching message arrives before the timeout', async () => { + const send = jest.fn().mockResolvedValue({}); + const { now, wait } = pollControl(); + await expect( + awaitMessageMatching(client(send), 'queue-url', () => false, 'a match', { + now, + wait, + timeoutMs: 200, + }), + ).rejects.toThrow('a match'); + }); +}); + +describe('purgeQueue', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('does nothing when the queue url is undefined', async () => { + const send = jest.fn(); + await purgeQueue(client(send), undefined); + expect(send).not.toHaveBeenCalled(); + }); + + it('purges the queue', async () => { + const send = jest.fn().mockResolvedValue({}); + await purgeQueue(client(send), 'queue-url'); + expect(PurgeQueueCommand).toHaveBeenCalledWith({ QueueUrl: 'queue-url' }); + }); + + it('swallows a PurgeQueueInProgress error', async () => { + const error = Object.assign(new Error('in progress'), { + name: 'PurgeQueueInProgress', + }); + const send = jest.fn().mockRejectedValue(error); + await expect( + purgeQueue(client(send), 'queue-url'), + ).resolves.toBeUndefined(); + }); + + it('rethrows other errors', async () => { + const send = jest.fn().mockRejectedValue(new Error('boom')); + await expect(purgeQueue(client(send), 'queue-url')).rejects.toThrow('boom'); + }); +}); + +describe('purgeQueues', () => { + it('purges every supplied queue url', async () => { + const send = jest.fn().mockResolvedValue({}); + await purgeQueues(client(send), ['a', undefined, 'b']); + expect(PurgeQueueCommand).toHaveBeenCalledTimes(2); + }); +}); diff --git a/packages/shared-utils/src/test-support/cloudwatch.ts b/packages/shared-utils/src/test-support/cloudwatch.ts new file mode 100644 index 0000000..7ea6b2f --- /dev/null +++ b/packages/shared-utils/src/test-support/cloudwatch.ts @@ -0,0 +1,90 @@ +import { + CloudWatchLogsClient, + FilterLogEventsCommand, + ThrottlingException, +} from '@aws-sdk/client-cloudwatch-logs'; + +import type { RegionOptions } from './deployment'; +import { type PollOptions, PollTimeoutError, pollUntil } from './poll'; + +export function createCloudWatchLogsClient({ + region, +}: RegionOptions): CloudWatchLogsClient { + return new CloudWatchLogsClient({ region }); +} + +export interface LogEntry { + message: string; +} + +export interface AwaitLogEntriesOptions extends PollOptions { + minCount?: number; + lookbackMs?: number; +} + +export async function queryLogEntries( + client: CloudWatchLogsClient, + logGroupName: string, + filterPattern: string, + startTime: number, + lookbackMs = 0, +): Promise { + const queryStartTime = Math.max(0, startTime - lookbackMs); + const response = await client.send( + new FilterLogEventsCommand({ + logGroupName, + startTime: queryStartTime, + filterPattern, + }), + ); + return (response.events ?? []) + .filter((event): event is typeof event & { message: string } => + Boolean(event.message), + ) + .map((event) => ({ message: event.message })); +} + +/** + * Polls a CloudWatch log group until at least `minCount` entries match the + * filter, returning whatever matched (possibly fewer than `minCount`) if the + * poll times out. CloudWatch throttling is retried rather than failing. + */ +export async function awaitMatchingLogEntries( + client: CloudWatchLogsClient, + logGroupName: string, + filterPattern: string, + startTime: number, + options: AwaitLogEntriesOptions = {}, +): Promise { + const minCount = options.minCount ?? 1; + const lookbackMs = options.lookbackMs ?? 0; + let matched: LogEntry[] = []; + + try { + await pollUntil( + async () => { + try { + matched = await queryLogEntries( + client, + logGroupName, + filterPattern, + startTime, + lookbackMs, + ); + return matched.length >= minCount; + } catch (error) { + if (error instanceof ThrottlingException) { + return false; + } + throw error; + } + }, + `log entries in ${logGroupName}`, + options, + ); + } catch (error) { + if (!(error instanceof PollTimeoutError)) throw error; + } + + return matched; +} diff --git a/packages/shared-utils/src/test-support/deployment.ts b/packages/shared-utils/src/test-support/deployment.ts new file mode 100644 index 0000000..51f1ff0 --- /dev/null +++ b/packages/shared-utils/src/test-support/deployment.ts @@ -0,0 +1,72 @@ +export interface DeploymentDetails { + region: string; + environment: string; + project: string; + component: string; + accountId: string; +} + +export interface DeploymentDetailsDefaults { + region?: string; + project?: string; + component?: string; +} + +export interface RegionOptions { + region: string; +} + +/** + * Reads deployment details from the environment. All per-repo defaults are + * passed in rather than hard-coded, so the helper stays generic across bounded + * contexts. A value is required from either the environment or the supplied + * defaults. + */ +export function getDeploymentDetails( + defaults: DeploymentDetailsDefaults = {}, +): DeploymentDetails { + const region = process.env.AWS_REGION ?? defaults.region; + const environment = process.env.ENVIRONMENT; + const project = process.env.PROJECT ?? defaults.project; + const component = process.env.COMPONENT ?? defaults.component; + const accountId = process.env.AWS_ACCOUNT_ID; + + if (!region) { + throw new Error( + 'AWS_REGION environment variable must be set or a default provided', + ); + } + + if (!environment) { + throw new Error('ENVIRONMENT environment variable must be set'); + } + + if (!project) { + throw new Error( + 'PROJECT environment variable must be set or a default provided', + ); + } + + if (!component) { + throw new Error( + 'COMPONENT environment variable must be set or a default provided', + ); + } + + if (!accountId) { + throw new Error('AWS_ACCOUNT_ID environment variable must be set'); + } + + return { region, environment, project, component, accountId }; +} + +export function buildLambdaLogGroupName( + { + component, + environment, + project, + }: Pick, + functionIdentifier: string, +): string { + return `/aws/lambda/${project}-${environment}-${component}-${functionIdentifier}`; +} diff --git a/packages/shared-utils/src/test-support/dynamodb.ts b/packages/shared-utils/src/test-support/dynamodb.ts new file mode 100644 index 0000000..e242717 --- /dev/null +++ b/packages/shared-utils/src/test-support/dynamodb.ts @@ -0,0 +1,12 @@ +import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; +import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb'; + +import type { RegionOptions } from './deployment'; + +export function createDynamoDbDocumentClient({ + region, +}: RegionOptions): DynamoDBDocumentClient { + return DynamoDBDocumentClient.from(new DynamoDBClient({ region }), { + marshallOptions: { removeUndefinedValues: true }, + }); +} diff --git a/packages/shared-utils/src/test-support/event-factory.ts b/packages/shared-utils/src/test-support/event-factory.ts new file mode 100644 index 0000000..9722f60 --- /dev/null +++ b/packages/shared-utils/src/test-support/event-factory.ts @@ -0,0 +1,27 @@ +/** + * Generic override-pattern helpers for building test event/data fixtures. + * Domain factories are built on top of these in each bounded context. + */ + +export function applyOverrides( + base: T, + overrides: Partial = {}, +): T { + return { ...base, ...overrides }; +} + +export interface EventOverrides { + event?: Partial; + data?: Partial; +} + +export function applyEventOverrides( + base: E, + overrides: EventOverrides = {}, +): E { + return { + ...base, + ...overrides.event, + data: { ...base.data, ...overrides.data }, + }; +} diff --git a/packages/shared-utils/src/test-support/eventbridge.ts b/packages/shared-utils/src/test-support/eventbridge.ts new file mode 100644 index 0000000..c030143 --- /dev/null +++ b/packages/shared-utils/src/test-support/eventbridge.ts @@ -0,0 +1,9 @@ +import { EventBridgeClient } from '@aws-sdk/client-eventbridge'; + +import type { RegionOptions } from './deployment'; + +export function createEventBridgeClient({ + region, +}: RegionOptions): EventBridgeClient { + return new EventBridgeClient({ region }); +} diff --git a/packages/shared-utils/src/test-support/index.ts b/packages/shared-utils/src/test-support/index.ts new file mode 100644 index 0000000..4c74383 --- /dev/null +++ b/packages/shared-utils/src/test-support/index.ts @@ -0,0 +1,16 @@ +export { buildLambdaLogGroupName, getDeploymentDetails } from './deployment'; +export type { + DeploymentDetails, + DeploymentDetailsDefaults, + RegionOptions, +} from './deployment'; +export { applyEventOverrides, applyOverrides } from './event-factory'; +export type { EventOverrides } from './event-factory'; +export { + DEFAULT_POLL_TIMEOUT_MS, + POLL_INTERVAL_MS, + PollTimeoutError, + pollUntil, + safeJsonParse, +} from './poll'; +export type { PollOptions } from './poll'; diff --git a/packages/shared-utils/src/test-support/poll.ts b/packages/shared-utils/src/test-support/poll.ts new file mode 100644 index 0000000..7f5fdf2 --- /dev/null +++ b/packages/shared-utils/src/test-support/poll.ts @@ -0,0 +1,58 @@ +export const POLL_INTERVAL_MS = 500; +export const DEFAULT_POLL_TIMEOUT_MS = 60_000; + +export class PollTimeoutError extends Error { + constructor(message: string) { + super(message); + this.name = 'PollTimeoutError'; + } +} + +export function safeJsonParse(text: string): unknown { + try { + return JSON.parse(text); + } catch { + return undefined; + } +} + +export function delay(ms: number): Promise { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); +} + +export interface PollOptions { + timeoutMs?: number; + intervalMs?: number; + now?: () => number; + wait?: (ms: number) => Promise; +} + +/** + * Repeatedly runs `attempt` until it resolves `true`, throwing a + * `PollTimeoutError` once the timeout elapses. `now`/`wait` are injectable to + * keep tests deterministic. + */ +export async function pollUntil( + attempt: () => Promise, + description: string, + options: PollOptions = {}, +): Promise { + const timeoutMs = options.timeoutMs ?? DEFAULT_POLL_TIMEOUT_MS; + const intervalMs = options.intervalMs ?? POLL_INTERVAL_MS; + const now = options.now ?? Date.now; + const wait = options.wait ?? delay; + const deadline = now() + timeoutMs; + + let done = await attempt(); + while (!done) { + if (now() >= deadline) { + throw new PollTimeoutError( + `Timed out after ${timeoutMs}ms — ${description}`, + ); + } + await wait(intervalMs); + done = await attempt(); + } +} diff --git a/packages/shared-utils/src/test-support/s3.ts b/packages/shared-utils/src/test-support/s3.ts new file mode 100644 index 0000000..3eee276 --- /dev/null +++ b/packages/shared-utils/src/test-support/s3.ts @@ -0,0 +1,7 @@ +import { S3Client } from '@aws-sdk/client-s3'; + +import type { RegionOptions } from './deployment'; + +export function createS3Client({ region }: RegionOptions): S3Client { + return new S3Client({ region }); +} diff --git a/packages/shared-utils/src/test-support/sqs.ts b/packages/shared-utils/src/test-support/sqs.ts new file mode 100644 index 0000000..342112b --- /dev/null +++ b/packages/shared-utils/src/test-support/sqs.ts @@ -0,0 +1,137 @@ +import { + ChangeMessageVisibilityCommand, + type Message, + PurgeQueueCommand, + ReceiveMessageCommand, + SQSClient, + SendMessageCommand, +} from '@aws-sdk/client-sqs'; + +import type { DeploymentDetails, RegionOptions } from './deployment'; +import { type PollOptions, pollUntil, safeJsonParse } from './poll'; + +export function createSqsClient({ region }: RegionOptions): SQSClient { + return new SQSClient({ region }); +} + +export interface BuildQueueUrlOptions { + fifo?: boolean; + appendQueueSuffix?: boolean; +} + +export function buildQueueUrl( + { accountId, component, environment, project, region }: DeploymentDetails, + name: string, + options: BuildQueueUrlOptions = {}, +): string { + const appendQueueSuffix = options.appendQueueSuffix ?? true; + const suffix = options.fifo ? 'queue.fifo' : 'queue'; + const csi = `${project}-${environment}-${component}`; + const queueName = appendQueueSuffix + ? `${csi}-${name}-${suffix}` + : `${csi}-${name}`; + return `https://sqs.${region}.amazonaws.com/${accountId}/${queueName}`; +} + +export interface SendSqsEventOptions { + messageGroupId?: string; + messageDeduplicationId?: string; +} + +export async function sendSqsEvent( + client: SQSClient, + queueUrl: string, + event: T, + options: SendSqsEventOptions = {}, +): Promise { + await client.send( + new SendMessageCommand({ + QueueUrl: queueUrl, + MessageBody: JSON.stringify(event), + MessageGroupId: options.messageGroupId, + MessageDeduplicationId: options.messageDeduplicationId, + }), + ); +} + +export interface AwaitMessageOptions extends PollOptions { + visibilityTimeoutSeconds?: number; + waitTimeSeconds?: number; + maxNumberOfMessages?: number; +} + +export async function awaitMessageMatching( + client: SQSClient, + queueUrl: string, + predicate: (body: unknown) => boolean, + description: string, + options: AwaitMessageOptions = {}, +): Promise { + const visibilityTimeout = options.visibilityTimeoutSeconds ?? 30; + const waitTimeSeconds = options.waitTimeSeconds ?? 5; + const maxNumberOfMessages = options.maxNumberOfMessages ?? 10; + let matched: Message | undefined; + + await pollUntil( + async () => { + const response = await client.send( + new ReceiveMessageCommand({ + QueueUrl: queueUrl, + AttributeNames: ['All'], + MessageAttributeNames: ['All'], + MaxNumberOfMessages: maxNumberOfMessages, + WaitTimeSeconds: waitTimeSeconds, + VisibilityTimeout: visibilityTimeout, + }), + ); + + const messages = response.Messages ?? []; + for (const message of messages) { + const parsed = message.Body ? safeJsonParse(message.Body) : undefined; + if (predicate(parsed)) { + matched = message; + return true; + } + if (message.ReceiptHandle) { + await client.send( + new ChangeMessageVisibilityCommand({ + QueueUrl: queueUrl, + ReceiptHandle: message.ReceiptHandle, + VisibilityTimeout: 0, + }), + ); + } + } + return false; + }, + description, + options, + ); + + return matched as Message; +} + +export async function purgeQueue( + client: SQSClient, + queueUrl: string | undefined, +): Promise { + if (!queueUrl) { + return; + } + + try { + await client.send(new PurgeQueueCommand({ QueueUrl: queueUrl })); + } catch (error) { + if (error instanceof Error && error.name === 'PurgeQueueInProgress') { + return; + } + throw error; + } +} + +export async function purgeQueues( + client: SQSClient, + queueUrls: (string | undefined)[], +): Promise { + await Promise.all(queueUrls.map((url) => purgeQueue(client, url))); +} diff --git a/packages/shared-utils/tsconfig.build.json b/packages/shared-utils/tsconfig.build.json new file mode 100644 index 0000000..87fa62d --- /dev/null +++ b/packages/shared-utils/tsconfig.build.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "types": ["node"], + "paths": { + "*": ["./src/*"] + } + }, + "exclude": [ + "node_modules", + "dist", + "src/**/__tests__/**", + "src/**/*.test.ts" + ], + "extends": "./tsconfig.json", + "include": [ + "src" + ] +} diff --git a/packages/shared-utils/tsconfig.json b/packages/shared-utils/tsconfig.json new file mode 100644 index 0000000..d0fcb7f --- /dev/null +++ b/packages/shared-utils/tsconfig.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "types": ["jest", "node"] + }, + "exclude": [ + "node_modules", + "dist" + ], + "extends": "../../tsconfig.base.json", + "include": [ + "src", + "./jest.config.ts" + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f6b88a..2707caa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,10 +5,29 @@ settings: excludeLinksFromLockfile: false catalogs: + aws: + '@aws-sdk/client-cloudwatch-logs': + specifier: ^3.1113.0 + version: 3.1113.0 + '@aws-sdk/client-dynamodb': + specifier: ^3.1113.0 + version: 3.1113.0 + '@aws-sdk/client-eventbridge': + specifier: ^3.1113.0 + version: 3.1113.0 + '@aws-sdk/client-s3': + specifier: ^3.1113.0 + version: 3.1113.0 + '@aws-sdk/client-sqs': + specifier: ^3.1113.0 + version: 3.1113.0 + '@aws-sdk/lib-dynamodb': + specifier: ^3.1113.0 + version: 3.1113.0 build: turbo: specifier: ^2.9.6 - version: 2.10.8 + version: 2.10.5 lint: '@eslint/js': specifier: ^9.39.4 @@ -24,7 +43,7 @@ catalogs: version: 8.65.0 '@typescript-eslint/parser': specifier: ^8.46.1 - version: 8.65.0 + version: 8.67.0 eslint: specifier: ^9.37.0 version: 9.39.5 @@ -45,7 +64,7 @@ catalogs: version: 4.17.1 eslint-plugin-jest: specifier: ^29.0.1 - version: 29.16.0 + version: 29.16.1 eslint-plugin-json: specifier: ^4.0.1 version: 4.0.1 @@ -75,7 +94,11 @@ catalogs: version: 61.0.2 typescript-eslint: specifier: ^8.46.1 - version: 8.65.0 + version: 8.67.0 + runtime: + pino: + specifier: ^10.3.1 + version: 10.3.1 test: '@types/jest': specifier: ^29.5.0 @@ -101,10 +124,13 @@ catalogs: tools: '@tsconfig/node22': specifier: ^22.0.5 - version: 22.0.5 + version: 22.0.6 '@types/aws-lambda': specifier: ^8.10.161 version: 8.10.162 + '@types/node': + specifier: ^24.12.0 + version: 24.13.3 esbuild: specifier: ^0.25.11 version: 0.25.12 @@ -113,7 +139,7 @@ catalogs: version: 10.9.2 tsx: specifier: ^4.20.6 - version: 4.23.5 + version: 4.23.12 typescript: specifier: ^5.9.3 version: 5.9.3 @@ -132,22 +158,22 @@ importers: version: 9.39.5 '@stylistic/eslint-plugin': specifier: catalog:lint - version: 3.1.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) + version: 3.1.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) '@stylistic/eslint-plugin-ts': specifier: catalog:lint - version: 4.4.1(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) + version: 4.4.1(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) '@tsconfig/node22': specifier: catalog:tools - version: 22.0.5 + version: 22.0.6 '@types/jest': specifier: catalog:test version: 29.5.14 '@typescript-eslint/eslint-plugin': specifier: catalog:lint - version: 8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) + version: 8.65.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) '@typescript-eslint/parser': specifier: catalog:lint - version: 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) + version: 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) esbuild: specifier: catalog:tools version: 0.25.12 @@ -156,22 +182,22 @@ importers: version: 9.39.5(supports-color@8.1.1) eslint-config-airbnb-extended: specifier: catalog:lint - version: 2.3.3(@stylistic/eslint-plugin@3.1.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.5(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.5(supports-color@8.1.1)))(eslint-plugin-react-hooks@7.1.1(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint-plugin-react@7.37.5(eslint@9.39.5(supports-color@8.1.1)))(eslint@9.39.5(supports-color@8.1.1))(typescript-eslint@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)) + version: 2.3.3(@stylistic/eslint-plugin@3.1.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint-import-resolver-typescript@4.4.5(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.5(supports-color@8.1.1)))(eslint-plugin-react-hooks@7.1.1(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint-plugin-react@7.37.5(eslint@9.39.5(supports-color@8.1.1)))(eslint@9.39.5(supports-color@8.1.1))(typescript-eslint@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)) eslint-config-prettier: specifier: catalog:lint version: 10.1.8(eslint@9.39.5(supports-color@8.1.1)) eslint-import-resolver-typescript: specifier: catalog:lint - version: 4.4.5(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1) + version: 4.4.5(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1) eslint-plugin-html: specifier: catalog:lint version: 8.1.4 eslint-plugin-import-x: specifier: catalog:lint - version: 4.17.1(@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1) + version: 4.17.1(@typescript-eslint/utils@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1) eslint-plugin-jest: specifier: catalog:lint - version: 29.16.0(@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3))(eslint@9.39.5(supports-color@8.1.1))(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)))(supports-color@8.1.1)(typescript@5.9.3) + version: 29.16.1(@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(supports-color@8.1.1)(typescript@6.0.3) eslint-plugin-json: specifier: catalog:lint version: 4.0.1 @@ -204,53 +230,98 @@ importers: version: 61.0.2(eslint@9.39.5(supports-color@8.1.1)) jest: specifier: catalog:test - version: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + version: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) jest-environment-jsdom: specifier: catalog:test version: 29.7.0(supports-color@8.1.1) jest-html-reporter: specifier: catalog:test - version: 4.4.0(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)))(supports-color@8.1.1) + version: 4.4.0(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(supports-color@8.1.1) jest-mock-extended: specifier: catalog:test - version: 4.0.1(@jest/globals@30.4.1(supports-color@8.1.1))(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)))(typescript@5.9.3) + version: 4.0.1(@jest/globals@29.7.0(supports-color@8.1.1))(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(typescript@6.0.3) lcov-result-merger: specifier: catalog:test version: 5.0.1 ts-jest: specifier: catalog:test - version: 29.4.12(@babel/core@7.29.7(supports-color@8.1.1))(@jest/transform@30.4.1(supports-color@8.1.1))(@jest/types@30.4.1)(babel-jest@30.4.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(esbuild@0.25.12)(jest-util@30.4.1)(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.4.12(@babel/core@7.29.7(supports-color@8.1.1))(@jest/transform@30.4.1(supports-color@8.1.1))(@jest/types@30.4.1)(babel-jest@29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(esbuild@0.25.12)(jest-util@30.4.1)(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(typescript@6.0.3) ts-node: specifier: catalog:tools - version: 10.9.2(@types/node@24.13.3)(typescript@5.9.3) + version: 10.9.2(@types/node@25.9.5)(typescript@6.0.3) tsx: specifier: catalog:tools - version: 4.23.5 + version: 4.23.12 turbo: specifier: catalog:build - version: 2.10.8 + version: 2.10.5 typescript-eslint: specifier: catalog:lint - version: 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) + version: 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) infrastructure/terraform/modules/eventpub/lambda/eventpub: dependencies: '@aws-sdk/client-eventbridge': specifier: ^3.1004.0 - version: 3.1101.0 + version: 3.1111.0 aws-sdk-client-mock: specifier: ^4.1.0 version: 4.1.0 devDependencies: jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + version: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) + + packages/shared-utils: + devDependencies: + '@aws-sdk/client-cloudwatch-logs': + specifier: catalog:aws + version: 3.1113.0 + '@aws-sdk/client-dynamodb': + specifier: catalog:aws + version: 3.1113.0 + '@aws-sdk/client-eventbridge': + specifier: catalog:aws + version: 3.1113.0 + '@aws-sdk/client-s3': + specifier: catalog:aws + version: 3.1113.0 + '@aws-sdk/client-sqs': + specifier: catalog:aws + version: 3.1113.0 + '@aws-sdk/lib-dynamodb': + specifier: catalog:aws + version: 3.1113.0(@aws-sdk/client-dynamodb@3.1113.0) + '@tsconfig/node22': + specifier: catalog:tools + version: 22.0.6 + '@types/jest': + specifier: catalog:test + version: 29.5.14 + '@types/node': + specifier: catalog:tools + version: 24.13.3 + eslint: + specifier: catalog:lint + version: 9.39.5(supports-color@8.1.1) + jest: + specifier: catalog:test + version: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) + pino: + specifier: catalog:runtime + version: 10.3.1 + ts-jest: + specifier: catalog:test + version: 29.4.12(@babel/core@7.29.7(supports-color@8.1.1))(@jest/transform@30.4.1(supports-color@8.1.1))(@jest/types@30.4.1)(babel-jest@29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(esbuild@0.28.2)(jest-util@30.4.1)(jest@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(typescript@5.9.3) + typescript: + specifier: catalog:tools + version: 5.9.3 src/lambdas/apim-access-token-refresher: dependencies: '@aws-sdk/client-ssm': specifier: ^3.840.0 - version: 3.1101.0 + version: 3.1111.0 axios: specifier: ^1.18.1 version: 1.19.0(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1) @@ -269,7 +340,7 @@ importers: devDependencies: '@tsconfig/node22': specifier: ^22.0.2 - version: 22.0.5 + version: 22.0.6 '@types/jest': specifier: ^29.5.14 version: 29.5.14 @@ -284,10 +355,10 @@ importers: version: 6.15.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + version: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) jest-mock-extended: specifier: ^3.0.7 - version: 3.0.7(jest@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)))(typescript@5.9.3) + version: 3.0.7(jest@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(typescript@5.9.3) typescript: specifier: ^5.8.2 version: 5.9.3 @@ -309,7 +380,7 @@ importers: devDependencies: '@tsconfig/node22': specifier: ^22.0.2 - version: 22.0.5 + version: 22.0.6 '@types/aws-lambda': specifier: ^8.10.148 version: 8.10.162 @@ -321,10 +392,10 @@ importers: version: 24.13.3 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + version: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) jest-mock-extended: specifier: ^3.0.7 - version: 3.0.7(jest@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)))(typescript@5.9.3) + version: 3.0.7(jest@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(typescript@5.9.3) typescript: specifier: ^5.8.2 version: 5.9.3 @@ -333,13 +404,13 @@ importers: dependencies: '@aws-sdk/client-lambda': specifier: ^3.984.0 - version: 3.1101.0 + version: 3.1111.0 '@aws-sdk/client-s3': specifier: ^3.984.0 - version: 3.1101.0 + version: 3.1111.0 '@aws-sdk/client-ssm': specifier: ^3.984.0 - version: 3.1101.0 + version: 3.1111.0 async-mutex: specifier: ^0.4.0 version: 0.4.1 @@ -355,10 +426,10 @@ importers: devDependencies: '@aws-sdk/types': specifier: ^3.914.0 - version: 3.974.2 + version: 3.974.4 '@tsconfig/node22': specifier: catalog:tools - version: 22.0.5 + version: 22.0.6 '@types/aws-lambda': specifier: catalog:tools version: 8.10.162 @@ -376,10 +447,10 @@ importers: version: 4.1.0(aws-sdk-client-mock@4.1.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + version: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) jest-mock-extended: specifier: ^3.0.7 - version: 3.0.7(jest@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)))(typescript@5.9.3) + version: 3.0.7(jest@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(typescript@5.9.3) typescript: specifier: catalog:tools version: 5.9.3 @@ -395,7 +466,7 @@ importers: devDependencies: '@tsconfig/node22': specifier: ^22.0.5 - version: 22.0.5 + version: 22.0.6 '@types/jest': specifier: ^29.5.0 version: 29.5.14 @@ -404,109 +475,154 @@ importers: version: 25.9.5 '@types/semver': specifier: ^7.5.8 - version: 7.8.0 + version: 7.7.1 globals: specifier: ^17.6.0 - version: 17.9.0 + version: 17.11.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + version: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) ts-jest: specifier: ^29.4.11 - version: 29.4.12(@babel/core@7.29.7(supports-color@8.1.1))(@jest/transform@30.4.1(supports-color@8.1.1))(@jest/types@30.4.1)(babel-jest@30.4.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(esbuild@0.28.1)(jest-util@30.4.1)(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)))(typescript@6.0.3) + version: 29.4.12(@babel/core@7.29.7(supports-color@8.1.1))(@jest/transform@30.4.1(supports-color@8.1.1))(@jest/types@30.4.1)(babel-jest@29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(esbuild@0.28.2)(jest-util@30.4.1)(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(typescript@6.0.3) tsx: specifier: ^4.22.0 - version: 4.23.5 + version: 4.23.12 typescript: specifier: ^6.0.3 version: 6.0.3 typescript-eslint: specifier: ^8.60.1 - version: 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + version: 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) packages: - '@aws-sdk/checksums@3.1000.24': - resolution: {integrity: sha512-7TWLjypP8kk3savsDBRuhZJx7mBuFFA2136BQhwwLllsAnO4Tmq/p+SXZaNxbuulkzUFz3BZzj0bb4YzexZcNQ==} + '@aws-sdk/checksums@3.1000.28': + resolution: {integrity: sha512-VCpnmyHQ1IH49ni3LXnQj7DPr7rmcJmzYeiCkYdCcfgNtkvOj38cdcL9lapBWoItZWFACJPFJlymqC7/gem3Gw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-cloudwatch-logs@3.1113.0': + resolution: {integrity: sha512-3CJoX7FvmH3MW7S1YZW0ztS3yMgTJKIzqKvg3I/nhN4cjjUwLkRUGdBmsR9vQOWmdVGCILqu/OdRaz6De3F5ww==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-dynamodb@3.1113.0': + resolution: {integrity: sha512-JuUT1NhoKzsA9jNkOWeOet9BhH5mEuA565mv3vtNhj6I3O8eoyG2FjMycxTKRozdKWwKkmUoj3bFCmhFNudKng==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-eventbridge@3.1111.0': + resolution: {integrity: sha512-gso1nBgj2PkeNe/jW+X+WQQlGHt+ok4poWsAmEyQ4xzM511JTVMpzGa+vIDu0fZ42QURbNXXXYjlguFAjkNojg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-eventbridge@3.1113.0': + resolution: {integrity: sha512-RG/7c2BaO/XhqCw44NOSrFQo1nSPN94htnswiKFnk8zCCy6GyFF8lfpsx45TGcYEDZc8rcRRwMbK4E9OErG6gg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-lambda@3.1111.0': + resolution: {integrity: sha512-jG2rB6LY2rx3XT55axgH3C0aIv1egvI0kqPYC6jfghVp82kWssU7R/1dJxXr0PnPLv4wq+WXRyLEmjyKURUjFQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-s3@3.1111.0': + resolution: {integrity: sha512-VnLT6aSTN8tWl/NsXUysXNZor7wQBp9CRwufo7kt8cwGXvHLZ0S/cV1K9WFcREGboVYSo3NGQ3ZvU7LRidh2aQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-s3@3.1113.0': + resolution: {integrity: sha512-NRqdtohoMRyWkEeeznfG1KPN08dclCbl+HFuLPB2v8qPcgoNmTFlLKl9ELiR6hsGXQ4Ur3qvRnoJVEk8ND74pg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-sqs@3.1113.0': + resolution: {integrity: sha512-H9Cjd/zAJwxMhFpzd0D0svvjA0A1SuGdjQCCkoFIBTzPrUUbOBQ+xrd6kzNPBHCyFyk9ecUeejLhMI460+QYig==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-ssm@3.1111.0': + resolution: {integrity: sha512-NhVyZL203unBVPi/oFQ48m0f5z/0M8nKM6nVEoOnX9/hfWXfa81rh5J1Tj4YoDuDjb5aTKyQZAtsbD48Dwiujw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/core@3.977.8': + resolution: {integrity: sha512-7+Kcrkvrk9lM/m7jRhHpT4jCdvzGHsuaSRbF8TdzzkY1mRzp/Ogwf9c7H29k4gGhey0BBWhCWr16+t0J61gwmg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-env@3.972.69': + resolution: {integrity: sha512-AreCFzcB4kH2HF9031Ot0jSJr3KXvRg6e8uDeub20JEVdZU3Bv0sTq1plc7VsT3KiqutlzH7l0j50UcCWHUioA==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-eventbridge@3.1101.0': - resolution: {integrity: sha512-BZwGOvV+FcPcQqcnBHL11+qgHsaLAz+x01m+ppDXHpI6Tzhy4zsgp2LXESGzkLDrSk4DnzItkF38q1j9VX0ZVA==} + '@aws-sdk/credential-provider-http@3.972.71': + resolution: {integrity: sha512-A8ObcqVmDMnk4F9NozZ7JwmUu9Q4xyBJkmyq1C5U+wNM9ht9J7+EuuyabsLWXZnOoTqFaJuYBYTKf5CTipkEjA==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-lambda@3.1101.0': - resolution: {integrity: sha512-OiMqyOfqWBMqh0Ov33uICt5ZXT/PQLUEDGXg9M+MinndyIEuJRuSONrmxUShQn6xjcjohCugpUSTjTrMUAt1UQ==} + '@aws-sdk/credential-provider-ini@3.973.14': + resolution: {integrity: sha512-7c+Wti2LsERNWMfm7ySz3/6RPopFW3Nmn7s63Xpcq6R/tRuY5hpvkHA2xVgi5ukJbvok9l0IDtVEvqTtg+X7dw==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-s3@3.1101.0': - resolution: {integrity: sha512-16EFb1aTEBgPcfUAWAjjlB57IZCyn7B3rlfT+xqE7M6WoH8AMMU3vFZO0UOitwh/xvvzVx73YED1/n0PU4qBMw==} + '@aws-sdk/credential-provider-login@3.972.76': + resolution: {integrity: sha512-LVixwOnEJfrrfKHeZjBA8pIMTZjNDq8ak8VpcoWUuCJDrSnBNU8POJksULMgvN089P0MXtQYH2Zs627/MK1K0g==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-ssm@3.1101.0': - resolution: {integrity: sha512-8R5aywNT7ccoTFsbqKB+XIh5LA+XgqlB0PnICFplZUM8NfJIENip9LTXv6weFIuruqiAe2gMS0K2pjO2gP+gUQ==} + '@aws-sdk/credential-provider-node@3.972.80': + resolution: {integrity: sha512-bE2qh8ww4iClO1jHsBXdOE8FUgzDbdxbyorNjSCoPSkQd51k3jODItuPZfuwcLHZqDXsH+bI4AMHhqtuyR7mSg==} engines: {node: '>=20.0.0'} - '@aws-sdk/core@3.977.4': - resolution: {integrity: sha512-CEkcQlMOQJCvul60U7wdAOACjtdgFWDsfJI+6wUOGdhGNV2lGbuJpi/R50QLpFG3Tp+sQxa/RmzC3X7KHbhuTA==} + '@aws-sdk/credential-provider-process@3.972.69': + resolution: {integrity: sha512-9kpTNdZTrcqXTfhxM7fgl9Z68ek3Fu5oe3Yf+A/pJGibEqpgZxz2tSY7SinmyCIU2PJ+ygY4FPoBBnLpocMtrQ==} engines: {node: '>=20.0.0'} - deprecated: |- - Deprecated due to Document number parsing bug in JSON, see - https://github.com/aws/aws-sdk-js-v3/issues/8246. Newer version available. - '@aws-sdk/credential-provider-env@3.972.65': - resolution: {integrity: sha512-lJT2aRw9wCV8jPHyFJjdZLD4HTydL6/22AnCSOB8e/LqOc55nEJGLHkJQeSxhn8QiqyjFwPKQFtMw0ovjRUY/g==} + '@aws-sdk/credential-provider-sso@3.973.13': + resolution: {integrity: sha512-Oc81qauMPzUoTnAS2YKpNwY6sY/LUyQTEeaf6yP197WMxkEBQfcKLR1MFpD7+pNTubXnfkH6gwpji+Gc7iyD2Q==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-http@3.972.67': - resolution: {integrity: sha512-N7fw/15hSwI/CPxe5ohOyb7O4ge9f5me1gVIn8OIkBRB0squ8OJqQyDyH/HoL+Sb1W5xdC88jVC+bHkw73iu+Q==} + '@aws-sdk/credential-provider-web-identity@3.972.75': + resolution: {integrity: sha512-YPN6uoGDgjjjeVFZrcOeCJqmB6zpXoeeNgIjqe+DexJaWqdjVfCCe+VAZwli9Z2h8KhFW8oxkO39emQ1tyz/Mw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-ini@3.973.10': - resolution: {integrity: sha512-Zh9XRaPnDN9buO7GfWBubS22R6Nq5D6hbyYEMN05LiOnXugm/8WDjUx6y756bSPbdn3aJB2qG4zFW3bN82QhoQ==} + '@aws-sdk/dynamodb-codec@3.973.43': + resolution: {integrity: sha512-5nw01fhFJEKM68n0R65S1DijiSAQWZVbvH7IxTIJpFFbggg816jBVYvhK7W+XISjvtdg0rMkF/gQmuLGH713mg==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-login@3.972.72': - resolution: {integrity: sha512-zZapIKwaHp7TdTf9hbH1I3CVUdEupmt7FXO/BoTQGC+4h6NkXKWpqF2p5WyfpjurDLHCpSyh+BzMlAg8arqWLA==} + '@aws-sdk/endpoint-cache@3.972.11': + resolution: {integrity: sha512-8q1ICxcDjHId3bBryuu/j+1L9y5/3uQnwzLDt5j2ElcjZSoWmFtymdJy7OjLrluSMe0Z4mq5bcH4fxBXvlEHfw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-node@3.972.76': - resolution: {integrity: sha512-1yzLmRiYSgGC25v7ZZEwJn/auhHHTIHgFOmzL2f36hf1+7jSLcX+1QrAz4760WEzPiiQl8xmlpFhHfl2OoyVzA==} + '@aws-sdk/lib-dynamodb@3.1113.0': + resolution: {integrity: sha512-Kp2xj7zjG2rzIoq63F6+wqudMthQBDnVqzr7izvXRgOTtgW5kDkfU0djrSlfgPbGQiWOuijzI5fgHY5afNb6qQ==} engines: {node: '>=20.0.0'} + peerDependencies: + '@aws-sdk/client-dynamodb': ^3.1113.0 - '@aws-sdk/credential-provider-process@3.972.65': - resolution: {integrity: sha512-e5DbbNteOSalN58U83G6kFa4ECLEuGbGqNBHIXE7zYXA/m4GHblIGjFbSH7wYv6gBV8iNSDcRZBKfQZF5vF9nw==} + '@aws-sdk/middleware-endpoint-discovery@3.972.29': + resolution: {integrity: sha512-cXW7QNIOhUSfccZmwJEjn9EdCAjzdOtt/+MtO5HWgxIZdhzyC1kNuQKIgGEDkgabxiXymWw0/VFWdqxqeLbgMA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-sso@3.973.9': - resolution: {integrity: sha512-0V0u4t+KBku9fbh5CPCaC5hUWwSzDafp8nCuDy817zWbp2gz80jO44rMQkiwnZ+k54B+tjAtzRy00DJRGTKGBg==} + '@aws-sdk/middleware-sdk-s3@3.972.74': + resolution: {integrity: sha512-2lzoV2z2QO5KJZYGOCnIZ1WVQgzMECvwuzr1xb034a++8QW4U4eGrmC2u4yg1xvNv4TLL/Uv5DLyuAiw0b9z7Q==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-web-identity@3.972.71': - resolution: {integrity: sha512-e4dwiRltGAaQ+2yxw57Hj0l/BF3BHiG14+QpYE7bGYBlpAq/fkIri2BDhjWon8c0mhhtd2txQBAkQb9BcTStFg==} + '@aws-sdk/middleware-sdk-sqs@3.972.41': + resolution: {integrity: sha512-07AbG/6LlaoC3YJ97vPgWVYFGWg3W3Bdr1ow3xjwti5u9/PjVD8+wB+qu2jDZnIvE6F7Y4ONWYCDQTPxiepdnA==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-sdk-s3@3.972.70': - resolution: {integrity: sha512-APdP0iODt39AkjCjzTFIoFrxDH/Cz3CpWRDKLcsJg7eOnfE1htkxL9BhDoe/xL7cXdoMwh2HBYv3DiT1uf64NQ==} + '@aws-sdk/nested-clients@3.997.43': + resolution: {integrity: sha512-bit+VpqWNyi3wHxFoTsTliNXimCSL2r2OeDTm7ZrG+YsTZ2D7ofDJ6r/t9PVBn80i6/v0X2h9Tgw6QP2MAKfPw==} engines: {node: '>=20.0.0'} - '@aws-sdk/nested-clients@3.997.39': - resolution: {integrity: sha512-wU5NPnj62Sb7A8xn/Zb+xThe05P3otNtDl37iOIi5DDMeCesNeCckaG+eXWGUs12Z9R34I8CD05TaTe6SIa61g==} + '@aws-sdk/signature-v4-multi-region@3.996.45': + resolution: {integrity: sha512-bBuyztukzXq6plzFGHAWiQt0QXo+HL8b8lX5cFTzkez/74PtS1c0qPFCIVuHkyoT+miH2qOjAcm1/yoro2ESPA==} engines: {node: '>=20.0.0'} - '@aws-sdk/signature-v4-multi-region@3.996.43': - resolution: {integrity: sha512-lKekx8bLBXSv4O+cslk9Zfnw2XKSkWBs3uWL5QGhH2ZAQfNS7FE0vcSSN2vD/AhxX54ZTywWxR4STThoeOXlBA==} + '@aws-sdk/token-providers@3.1111.0': + resolution: {integrity: sha512-JfljgoVtl+s3Qy21n9a7Z48uCQaOXcN74KJ3TEQfPoB293GrXFSt6HSQJF1sTZ8c/5QedEvd3NjJQMO4u9qa5A==} engines: {node: '>=20.0.0'} - '@aws-sdk/token-providers@3.1100.0': - resolution: {integrity: sha512-THf3MkgY3fNJZ3zdgSenLqR7gSE68KccCj1RCKretlG73Ppszvues02VpCUO9NlB/tZDC483FvGCld+AiPCkvg==} + '@aws-sdk/types@3.974.4': + resolution: {integrity: sha512-dSFDNG00MEz0/xl5gxL62giLd1iYyJsTxZ1I1DOj6lC+bbgLB4TRsYClJg3b62dhXT1uATzsTNXPnC+33EJV3A==} engines: {node: '>=20.0.0'} - '@aws-sdk/types@3.974.2': - resolution: {integrity: sha512-3W6IUtSxFbH6X7Wb7DzGCV5QiFQsd0g8bOfntpmDxQlzBoKWUMBu/JPQR0DwkE+Hpnxd6db1tXbOwdeHddG6cA==} + '@aws-sdk/util-dynamodb@3.996.9': + resolution: {integrity: sha512-16x2tRvl7OYpZ0W/DdFJieFriD13+RvuRBDbe5sj/tCEfK86HSGd7I2s5j0ivz8p6KWGkS+5wKRO9OliJkjUOQ==} engines: {node: '>=20.0.0'} + peerDependencies: + '@aws-sdk/client-dynamodb': ^3.1111.0 - '@aws-sdk/xml-builder@3.972.37': - resolution: {integrity: sha512-zKq4HQum8JwDyEuyfuI4bbiAcU0KxP6qy+9PR/IsR92IyE/DaBAikzAS50tjxip4bqIIANpCcG+Yyj6CVhXupg==} + '@aws-sdk/xml-builder@3.972.39': + resolution: {integrity: sha512-FTti8DS5MMWXNUWiRwXAJeYS+0GHHiMy0+7XOhcwk63ILHmfS2UFy2z/HNpZCSOJJ3P3dnWY6hfYNW3DF0nXUA==} engines: {node: '>=20.0.0'} '@aws/lambda-invoke-store@0.3.0': @@ -704,8 +820,8 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.28.1': - resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} + '@esbuild/aix-ppc64@0.28.2': + resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -716,8 +832,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.28.1': - resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} + '@esbuild/android-arm64@0.28.2': + resolution: {integrity: sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -728,8 +844,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.28.1': - resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} + '@esbuild/android-arm@0.28.2': + resolution: {integrity: sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -740,8 +856,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.28.1': - resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} + '@esbuild/android-x64@0.28.2': + resolution: {integrity: sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -752,8 +868,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.28.1': - resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} + '@esbuild/darwin-arm64@0.28.2': + resolution: {integrity: sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -764,8 +880,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.28.1': - resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} + '@esbuild/darwin-x64@0.28.2': + resolution: {integrity: sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -776,8 +892,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.28.1': - resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} + '@esbuild/freebsd-arm64@0.28.2': + resolution: {integrity: sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -788,8 +904,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.28.1': - resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} + '@esbuild/freebsd-x64@0.28.2': + resolution: {integrity: sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -800,8 +916,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.28.1': - resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} + '@esbuild/linux-arm64@0.28.2': + resolution: {integrity: sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -812,8 +928,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.28.1': - resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} + '@esbuild/linux-arm@0.28.2': + resolution: {integrity: sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -824,8 +940,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.28.1': - resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} + '@esbuild/linux-ia32@0.28.2': + resolution: {integrity: sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -836,8 +952,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.28.1': - resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} + '@esbuild/linux-loong64@0.28.2': + resolution: {integrity: sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -848,8 +964,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.28.1': - resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} + '@esbuild/linux-mips64el@0.28.2': + resolution: {integrity: sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -860,8 +976,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.28.1': - resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} + '@esbuild/linux-ppc64@0.28.2': + resolution: {integrity: sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -872,8 +988,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.28.1': - resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} + '@esbuild/linux-riscv64@0.28.2': + resolution: {integrity: sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -884,8 +1000,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.28.1': - resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} + '@esbuild/linux-s390x@0.28.2': + resolution: {integrity: sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -896,8 +1012,8 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.28.1': - resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} + '@esbuild/linux-x64@0.28.2': + resolution: {integrity: sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==} engines: {node: '>=18'} cpu: [x64] os: [linux] @@ -908,8 +1024,8 @@ packages: cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-arm64@0.28.1': - resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} + '@esbuild/netbsd-arm64@0.28.2': + resolution: {integrity: sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] @@ -920,8 +1036,8 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.28.1': - resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} + '@esbuild/netbsd-x64@0.28.2': + resolution: {integrity: sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] @@ -932,8 +1048,8 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.28.1': - resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} + '@esbuild/openbsd-arm64@0.28.2': + resolution: {integrity: sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -944,8 +1060,8 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.28.1': - resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} + '@esbuild/openbsd-x64@0.28.2': + resolution: {integrity: sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] @@ -956,8 +1072,8 @@ packages: cpu: [arm64] os: [openharmony] - '@esbuild/openharmony-arm64@0.28.1': - resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} + '@esbuild/openharmony-arm64@0.28.2': + resolution: {integrity: sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] @@ -968,8 +1084,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.28.1': - resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} + '@esbuild/sunos-x64@0.28.2': + resolution: {integrity: sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -980,8 +1096,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.28.1': - resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} + '@esbuild/win32-arm64@0.28.2': + resolution: {integrity: sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -992,8 +1108,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.28.1': - resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} + '@esbuild/win32-ia32@0.28.2': + resolution: {integrity: sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -1004,8 +1120,8 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.28.1': - resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} + '@esbuild/win32-x64@0.28.2': + resolution: {integrity: sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -1113,10 +1229,6 @@ packages: resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/environment@30.4.1': - resolution: {integrity: sha512-AK9yNRqgKxiabqMoe4oW+3/TSSeV8vkdC7BGaxZdU0AFXfOpofTLqdru2GXKZghP3sdgwE9XXpnVwfZ8JnFV4w==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/expect-utils@29.7.0': resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1129,18 +1241,10 @@ packages: resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/expect@30.4.1': - resolution: {integrity: sha512-ginrj6TMgh2GshLUGCjO94Ptx9HhdZA/I6A9iUfyeLKFtdAjnKzHDgzgP9HYQgbxM1lbXScQ2eUBz2lGeVDPWA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/fake-timers@29.7.0': resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/fake-timers@30.4.1': - resolution: {integrity: sha512-iW5umdmfPeWzehrVhugFQZqCchSCud5S1l2YT0O9ZhjRR0ExclANDZkiSBwzqtnlOn0J1JXvO+HZ6rkuyOVOgQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/get-type@30.1.0': resolution: {integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -1149,10 +1253,6 @@ packages: resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/globals@30.4.1': - resolution: {integrity: sha512-ZbuY4cmXC8DkxYjfvT2DbcHWL2T6vmsMhXCDcmTB2T0y0gaezBI77ufq5ZAIdcRkYZ7NEQEDg1xFeKbxUJ5v5Q==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/pattern@30.4.0': resolution: {integrity: sha512-RAWn3+f9u8BsHijKJ71uHcFp6vmyEt6VvoWXkl6hKF3qVIuWNmudVjg12DlBPGup/frIl5UcUlH5HfEuvHpEXg==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -1183,10 +1283,6 @@ packages: resolution: {integrity: sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/snapshot-utils@30.4.1': - resolution: {integrity: sha512-ObY4ljvQ95mt6iwKtVLetR/4yXiAgl3H4nJxhztr0MTjrN97TwDYrnCp/kF60Ec9HdhkWTHSu+Hg05aXfngpOA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/source-map@29.6.3': resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1238,12 +1334,12 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@napi-rs/wasm-runtime@1.2.2': - resolution: {integrity: sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==} + '@napi-rs/wasm-runtime@1.2.3': + resolution: {integrity: sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==} engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} peerDependencies: - '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.3 - '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.3 + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -1257,6 +1353,9 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@pinojs/redact@0.4.0': + resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -1286,28 +1385,28 @@ packages: '@sinonjs/samsam@8.0.3': resolution: {integrity: sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ==} - '@smithy/core@3.31.1': - resolution: {integrity: sha512-CyogUINxvi7C7LDsh8Syo6hVJOT9ckz4rG8dRZfTJ8r91HkMY59PnNooaj7WcHyxEkxPfBAmbgztZU+xTo76lg==} + '@smithy/core@3.33.2': + resolution: {integrity: sha512-CUGXpnPkVdjUCbix+83sWLW9VFgQOm44MDOx/ihITJMAnOZKvL8YYIc7DR9pP/tZ8CIRvMiON/TucvygqbHO3w==} engines: {node: '>=18.0.0'} - '@smithy/credential-provider-imds@4.4.16': - resolution: {integrity: sha512-QfuLWAkLzptffFW980AFeHZFdqds2B64rpEd3uJ6lgs3xVn9QegGMUgUcj+4d7dRrAsya3r58ZKpku97WcFb4w==} + '@smithy/credential-provider-imds@4.5.2': + resolution: {integrity: sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg==} engines: {node: '>=18.0.0'} - '@smithy/fetch-http-handler@5.6.13': - resolution: {integrity: sha512-4fW86pEUOMbrD5nkbyl/tTvPHHWJFbuB2odl6ps9lWfHoXf9HWh3Q/Smh59qH1g7+c/BSZghX6bbUk4gsiMs8A==} + '@smithy/fetch-http-handler@5.7.2': + resolution: {integrity: sha512-nZyWTmSpJEXl6VtWVMBJve/7x12DZu6sIX1z1a+ZMaHlQQRs9Zpu6NbTe/gmxYXVRpkjxyDYpZ5gx2IM6f/Wkw==} engines: {node: '>=18.0.0'} - '@smithy/node-http-handler@4.9.13': - resolution: {integrity: sha512-Nmd/Nl35zfYrd+a6OO2cDJb3GPh9bgTjIUhcM+JFfjpp8/osCgboDV5nCT1I01Pv6R13eSKDKLSoVa5ZB6Zsfw==} + '@smithy/node-http-handler@4.11.2': + resolution: {integrity: sha512-avwAh9HM3h2lcfjvP3zYIZGf+XVgLQ91wOJ2qoFbNpW1UZeZb33aGlhTZvtkANHfcGhJroRY64525OjfgOg30g==} engines: {node: '>=18.0.0'} - '@smithy/signature-v4@5.6.12': - resolution: {integrity: sha512-I6KLtq3H0qqSuV9vLglfi8puHqzygzWHOnI4z/Rdoo+q50vvo18vBRdPAvvEtcaKROz7Zn6qnPa14kRfPH6PcQ==} + '@smithy/signature-v4@5.7.2': + resolution: {integrity: sha512-P7Ki6px6OOrxVtx8K7nLmyx4SlXUW/uTKDdMG44UHefmPGSRMBKe2v+TM59WdLcpUIrBrnuCsIqiM2MbsZjmhw==} engines: {node: '>=18.0.0'} - '@smithy/types@4.16.1': - resolution: {integrity: sha512-0JFs3V2y2M9tKW5na/qxe69Zv+uxLMO7QBbhxF/FHu/Gp2NFZAAL9tWl9PU02xxo07pb3G9FTyjNc6D5uZrJIg==} + '@smithy/types@4.17.2': + resolution: {integrity: sha512-FOKpVZob9MPTn2znRzGrnsMHv7BOsKVw3XiP/cOyYLDVZ9qKp4nifIiSCuUU/fIj5Vu0UOAxCFr+qRAtG0NUkA==} engines: {node: '>=18.0.0'} '@so-ric/colorspace@1.1.6': @@ -1332,8 +1431,8 @@ packages: resolution: {integrity: sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==} engines: {node: '>= 10'} - '@tsconfig/node10@1.0.12': - resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} + '@tsconfig/node10@1.0.13': + resolution: {integrity: sha512-gcLdvR9HO1ZJBypsOGqaP6TFEzb6vIta0KSTLt9NAQ6pXQO3cRgSVyCN6pzYqI9DlJgY71XKO0dpDhCf08b3pg==} '@tsconfig/node12@1.0.11': resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} @@ -1344,36 +1443,36 @@ packages: '@tsconfig/node16@1.0.4': resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - '@tsconfig/node22@22.0.5': - resolution: {integrity: sha512-hLf2ld+sYN/BtOJjHUWOk568dvjFQkHnLNa6zce25GIH+vxKfvTgm3qpaH6ToF5tu/NN0IH66s+Bb5wElHrLcw==} + '@tsconfig/node22@22.0.6': + resolution: {integrity: sha512-/5thavHAnWDZwH2H6eEn/T8pBEBhtuKaWGMslsj82kJfvzQgOgEMK7X4goBbIUjgVtAzPTtM9Ml64LA0uxO6Iw==} - '@turbo/darwin-64@2.10.8': - resolution: {integrity: sha512-po+7rfJfUnFXjWlcoN2RwhErgzCdRtBc1T26vYPcywHlggmCQiQe1uWaE4j+BibI2uY9/2pDoFzMN0rmSaPFOw==} + '@turbo/darwin-64@2.10.5': + resolution: {integrity: sha512-ENvPwy3x5yS7MwNYHeWjqOBXkwIMp39Pd+/zXC6PoiNzF8EIvvLZOZZ+ny6L9x4WgS5vxUii2LM5gM+zjPdnWw==} cpu: [x64] os: [darwin] - '@turbo/darwin-arm64@2.10.8': - resolution: {integrity: sha512-+zB2btDJ00lnPRuqOvpVvgl4x34k/djZQGZTTCfjn7JgNCl8QFY5Njo5+dqkY1g/+9gbbsnAvWm9CmJg9ebcXA==} + '@turbo/darwin-arm64@2.10.5': + resolution: {integrity: sha512-rqROo9zsF/P9RqsdtbLD1nFJicjSrYyvQ9kNJC38AbxA3pAs6VAlATvtvOFx7bqOv6vicf20SP9kF33avJjy2w==} cpu: [arm64] os: [darwin] - '@turbo/linux-64@2.10.8': - resolution: {integrity: sha512-K1dxqiVisyN7cViVsfQLs6xscQbYuI8aO2nbUhFURDACgEDfZRdP/b4CCxeosBJpcMfhYyiibWqJorCnvz9kKg==} + '@turbo/linux-64@2.10.5': + resolution: {integrity: sha512-RoSSiNFUxi27zLJuM9F6GyWWjHgLch9t6nwD6K0FkXRirZkTLlzIj6IhFnK8H9++nefLtdFqylE4vGjZAv6AAA==} cpu: [x64] - os: [android, linux] + os: [linux] - '@turbo/linux-arm64@2.10.8': - resolution: {integrity: sha512-Gi77ibVnrE1fEmvr+/wBD/yvRqhwp/RQuCp2+//lv1U1wNFFyVg0V7Wj8FG9FXPFAw5QHReo8rxc9+wBSDZjzA==} + '@turbo/linux-arm64@2.10.5': + resolution: {integrity: sha512-4ZComcpzmHGmVynQqvvi+iZOSq/tBvY1SltXB8g4NZRsrA01W8E+yRL8RNM+PLoyWsrCnJa8xa+DkWkv+xg4iQ==} cpu: [arm64] - os: [android, linux] + os: [linux] - '@turbo/windows-64@2.10.8': - resolution: {integrity: sha512-znnLO1haJPYTHoKMKwlAvlkjRiYbbhBzME6wIGaMd+fwir23U6jVd1ecaTWWi1fbnRVqxMfgDBKseQ/hLKb83g==} + '@turbo/windows-64@2.10.5': + resolution: {integrity: sha512-eL2Iyj4DbMINq1Sr1w0iAi6nAiZOF16KSlRGwCJpVh+IWZeY33MAsLHVOBMj1xoFtncVJXclCVpTPL2nBoYkFg==} cpu: [x64] os: [win32] - '@turbo/windows-arm64@2.10.8': - resolution: {integrity: sha512-VN30vh3b3Czh2WzYHNTfF1FE0YMZ5aHsLO8dBMGHJewA6792wX6iJR8ZxlzFW6WdOu0gEAKIvlYhfyT81Wkm4Q==} + '@turbo/windows-arm64@2.10.5': + resolution: {integrity: sha512-sog+wP+8YSJrdWZ/rUJg8xghVTrwoG+BrSlDQpnK5fzSgJHn1INRWXbVWRH0d3vX8dBI01E3yxXRre9Dn+OXQA==} cpu: [arm64] os: [win32] @@ -1440,8 +1539,8 @@ packages: '@types/qs@6.15.1': resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==} - '@types/semver@7.8.0': - resolution: {integrity: sha512-1mAINjtQCXXeLkJ9ehXkwOcBpqtLxiVtKhpUf83DdRNdQKV0iXZpaHYqRr7nj+wvxuJzoAmAwXI+sCNMv1CzLQ==} + '@types/semver@7.7.1': + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} '@types/sinon@17.0.4': resolution: {integrity: sha512-RHnIrhfPO3+tJT0s7cFaXGZvsL4bbR3/k7z3P312qMS4JaS2Tk+KiwiLx1S0rQ56ERj00u1/BtdyVd0FY+Pdew==} @@ -1472,8 +1571,16 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.65.0': - resolution: {integrity: sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA==} + '@typescript-eslint/eslint-plugin@8.67.0': + resolution: {integrity: sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.67.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/parser@8.67.0': + resolution: {integrity: sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 @@ -1485,16 +1592,32 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/project-service@8.67.0': + resolution: {integrity: sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/scope-manager@8.65.0': resolution: {integrity: sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.67.0': + resolution: {integrity: sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/tsconfig-utils@8.65.0': resolution: {integrity: sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/tsconfig-utils@8.67.0': + resolution: {integrity: sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/type-utils@8.65.0': resolution: {integrity: sha512-YjaZ7PRI5qY7ax2L3PbvX0rRyGtipAReCWs0mhhDBHjH/vl0g0BonaGXrKdKpMbIIsMIwDgbk/xzkBTyAltS5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1502,16 +1625,33 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/type-utils@8.67.0': + resolution: {integrity: sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/types@8.65.0': resolution: {integrity: sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.67.0': + resolution: {integrity: sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.65.0': resolution: {integrity: sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/typescript-estree@8.67.0': + resolution: {integrity: sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/utils@8.65.0': resolution: {integrity: sha512-gXiwIHsYreboxeJucHKPvgwl7dXt50mF8s1/c00cP/WoVTyWKFdtfhRWwZiXYFU5H2O8vVoSLNrexFZjYS/SGA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1519,10 +1659,21 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/utils@8.67.0': + resolution: {integrity: sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/visitor-keys@8.65.0': resolution: {integrity: sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.67.0': + resolution: {integrity: sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.3.3': resolution: {integrity: sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==} @@ -1694,8 +1845,8 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + ansi-regex@6.3.0: + resolution: {integrity: sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==} engines: {node: '>=12'} ansi-styles@4.3.0: @@ -1775,6 +1926,10 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -1791,8 +1946,8 @@ packages: aws-sdk-client-mock@4.1.0: resolution: {integrity: sha512-h/tOYTkXEsAcV3//6C1/7U4ifSpKyJvb6auveAepqqNJl6TdZaPFEtKjBQNf8UxQdDP850knB2i/whq4zlsxJw==} - axe-core@4.12.1: - resolution: {integrity: sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA==} + axe-core@4.13.0: + resolution: {integrity: sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A==} engines: {node: '>=4'} axios@1.19.0: @@ -1808,12 +1963,6 @@ packages: peerDependencies: '@babel/core': ^7.8.0 - babel-jest@30.4.1: - resolution: {integrity: sha512-fATAbM8piYxkiXQp3RBXmZHxZVNJZAVXXfyeyCN2Tida3+qJ8ea9UxhiJ2y4fLO90ZImKt6k9FlcH2+rLkJGhw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - peerDependencies: - '@babel/core': ^7.11.0 || ^8.0.0-0 - babel-plugin-istanbul@6.1.1: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} engines: {node: '>=8'} @@ -1826,10 +1975,6 @@ packages: resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - babel-plugin-jest-hoist@30.4.0: - resolution: {integrity: sha512-9EdtWM/sSfXLOGLwSn+GS6pIXyBnL07/8gyJlwFXjWy4DxMOyItqyUT29d4lQiS380EZwYlX7/At4PgBS+m2aA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - babel-preset-current-node-syntax@1.2.0: resolution: {integrity: sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==} peerDependencies: @@ -1841,12 +1986,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - babel-preset-jest@30.4.0: - resolution: {integrity: sha512-lBY4jxsNmCnSiu7kquw8ZC9F4+XLMOKypT3RnNHPvU2Kpd4W0xaPuLr5ZkRyOsvLYAY4yaW1ZwTW4xB7NIiZzg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - peerDependencies: - '@babel/core': ^7.11.0 || ^8.0.0-beta.1 - balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -1854,8 +1993,8 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - baseline-browser-mapping@2.11.11: - resolution: {integrity: sha512-/yImnXwyTvgMkhgekLHok/Rx5vO6E0BmStWlSqKWMVm2a2ITuZ1Tn+9bgLS+gZRdZmWtd8nxuhHpdmCUOWsTQQ==} + baseline-browser-mapping@2.11.14: + resolution: {integrity: sha512-JyJ954WzuIR8/FFzX0o5krdSTrBAkcCSRfWSleRsIHSWV+cZe2FI1PKggVkFke1hBldRs+LRxUczzE9iPmgZww==} engines: {node: '>=6.0.0'} hasBin: true @@ -1876,8 +2015,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.28.7: - resolution: {integrity: sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==} + browserslist@4.28.8: + resolution: {integrity: sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1930,8 +2069,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001806: - resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==} + caniuse-lite@1.0.30001809: + resolution: {integrity: sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==} chai@6.2.2: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} @@ -2004,8 +2143,8 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} - comment-parser@1.4.7: - resolution: {integrity: sha512-0h+uSNtQGW3D98eQt3jJ8L06Fves8hncB4V/PKdw/Qb8Hnk19VaKuTr55UNRYiSoVa7WwrFls+rh3ux9agmkeQ==} + comment-parser@1.4.8: + resolution: {integrity: sha512-rKZTGo4fzKYna8UcL0isTg5wkBNla7bxTypLwZQXjIdi++IdP1OJ41rI5Mti3/jltkPujbu4i9LIARYA+zpotQ==} engines: {node: '>= 12.0.0'} concat-map@0.0.1: @@ -2017,8 +2156,9 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - core-js-compat@3.49.0: - resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==} + core-js-compat@3.50.0: + resolution: {integrity: sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==} + engines: {node: '>=6.4.0'} create-jest@29.7.0: resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} @@ -2154,8 +2294,8 @@ packages: ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} - electron-to-chromium@1.5.399: - resolution: {integrity: sha512-lEcqhErbHjXRvd41rnWLpzbyU/IXfIYo7QwaFWmxGeLiLyY2TBCdHnWY88vB+p3ubnihRypDm66panXl7TylLA==} + electron-to-chromium@1.5.408: + resolution: {integrity: sha512-SLoprcYpJ/OH2v2ps0+N5biv9H4/KBT3+YmmDew64TwK5y9j2wv7pMOFY7IorVkyMtEyLSCRlXKLsNlakeAlPw==} emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -2226,8 +2366,8 @@ packages: engines: {node: '>=18'} hasBin: true - esbuild@0.28.1: - resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} + esbuild@0.28.2: + resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==} engines: {node: '>=18'} hasBin: true @@ -2337,8 +2477,8 @@ packages: eslint-import-resolver-node: optional: true - eslint-plugin-jest@29.16.0: - resolution: {integrity: sha512-0WFBxDHlT2ratGQfnFQEVIsgQJ5cfd+0IV8Kc6U3X2onB8ATLG23voD2Ch5G9fCkEpCPmCMuzW0tbS0kYb8biw==} + eslint-plugin-jest@29.16.1: + resolution: {integrity: sha512-tfxOIsjzaBud+f74aLbBMRcnrztt5eCIgnAdeoGdnzMAQ4IdAa/s/p8Ls55mk9MC79N3j2jbv4Qetz6Hclbcfw==} engines: {node: ^20.12.0 || ^22.0.0 || >=24.0.0} peerDependencies: '@typescript-eslint/eslint-plugin': ^8.0.0 @@ -2622,8 +2762,8 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} - get-tsconfig@4.14.1: - resolution: {integrity: sha512-Dz/6HxkrxgNehhxLVeyv8sad9UzF2xBVeaKBQNDfJ5XiSXmp2gTR0eO0RWiT2NCKS5aGP9jjkOMggTN90qU50A==} + get-tsconfig@4.14.2: + resolution: {integrity: sha512-XpwZALwwl/BaKTAyC6+c5T8y6kCg2jk+XGqOVrKIQmW49pNypYLMRjCUXqa28tQgJlhS2RlzP7sc+Rx7W6qsfw==} glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -2650,8 +2790,8 @@ packages: resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} engines: {node: '>=18'} - globals@17.9.0: - resolution: {integrity: sha512-m/MvAW61QVU5VDNF1Vj8axt016h8w7L5TU1e9zlab7XIttAT2YAlCwl75K1fOqvMM9apmD7lbCIRhpfkhmxhCg==} + globals@17.11.0: + resolution: {integrity: sha512-Z2I8hM+PbJDXQDq3Icgpzv+mPdwr68iZUU9d5WW4FuXfDUQfkZaZuvjMv42/5crNyw154+9+VWXbYrUgDXbxNw==} engines: {node: '>=18'} globalthis@1.0.4: @@ -3090,10 +3230,6 @@ packages: resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-snapshot@30.4.1: - resolution: {integrity: sha512-tEOkkfOMppUyeiHwjZswOQ3lcnoTnws/q5FnGIaeIh/jmoU0ZlgMYRR8sTlTj+nNGCoJ0RDq6SfxGxCsyMTPmw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-util@29.7.0: resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -3351,6 +3487,9 @@ packages: engines: {node: '>=10'} hasBin: true + mnemonist@0.38.3: + resolution: {integrity: sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -3378,8 +3517,8 @@ packages: node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - node-releases@2.0.51: - resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==} + node-releases@2.0.53: + resolution: {integrity: sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==} engines: {node: '>=18'} normalize-path@3.0.0: @@ -3421,6 +3560,13 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} + obliterator@1.6.1: + resolution: {integrity: sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==} + + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -3506,6 +3652,16 @@ packages: resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} engines: {node: '>=12'} + pino-abstract-transport@3.0.0: + resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==} + + pino-std-serializers@7.1.0: + resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==} + + pino@10.3.1: + resolution: {integrity: sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==} + hasBin: true + pirates@4.0.7: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} @@ -3543,6 +3699,9 @@ packages: resolution: {integrity: sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + process-warning@5.1.0: + resolution: {integrity: sha512-jQSaVHsPgtyw60e1rQ/A+/ArPEj/S8pS/vFnyGa/gYFXrKk/6RuDkoqVDQ5NI5MmS01698ltlAk0NoDBNLujRw==} + prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} @@ -3574,6 +3733,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -3587,6 +3749,13 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + + real-require@1.0.0: + resolution: {integrity: sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g==} + refa@0.12.1: resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -3754,6 +3923,9 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} + sonic-boom@4.2.1: + resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} + source-map-support@0.5.13: resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} @@ -3761,6 +3933,10 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -3867,6 +4043,10 @@ packages: text-hex@1.0.0: resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + thread-stream@4.2.0: + resolution: {integrity: sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ==} + engines: {node: '>=20'} + tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} @@ -3952,13 +4132,13 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.23.5: - resolution: {integrity: sha512-rw55FUaqOoI7RvlQwLbhO4nSDApnQ4/CykPuiQ/EPvtrX3WA9Ig55jIt9VvbBJbzJuj12ueRu4PMZ2SxPVbihg==} + tsx@4.23.12: + resolution: {integrity: sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q==} engines: {node: '>=18.0.0'} hasBin: true - turbo@2.10.8: - resolution: {integrity: sha512-9+8YX5QOkGXzZxcIykTHgaooRHGMWO+jfdyRK0o+rN0U7hBIig2MrJ8r/aNzIPDPhdA73SGb0O+tIztaModTMg==} + turbo@2.10.5: + resolution: {integrity: sha512-07Y/C7OUp23l4P92PJoYtFNbHjLhftrZH5Ce7dbczS4kX2Re+wtbXvZLoxn/pUtzgsQaRCBaRuZPJp4zmAn0WQ==} hasBin: true type-check@0.4.0: @@ -3997,8 +4177,8 @@ packages: resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==} engines: {node: '>= 0.4'} - typescript-eslint@8.65.0: - resolution: {integrity: sha512-/ggrHAwyjENDusvyxbuqxAC2dTnZg/Z8F+fgQtYIz+L6n/9HfSlEZcFGV/NsMNa6CkGk0xUjUAFwC0vHOflvIA==} + typescript-eslint@8.67.0: + resolution: {integrity: sha512-S2udFs8tCKEKffuJ4TB1idGUZiXdCPGi3IPBGWXarbLQ5UPXORV8QEVzJ4gCRduURMb5EkpNCdjbk0eDIuI8Yg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 @@ -4036,8 +4216,8 @@ packages: unrs-resolver@1.12.2: resolution: {integrity: sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==} - update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + update-browserslist-db@1.3.1: + resolution: {integrity: sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -4152,8 +4332,8 @@ packages: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - ws@8.21.1: - resolution: {integrity: sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==} + ws@8.21.3: + resolution: {integrity: sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -4222,201 +4402,304 @@ packages: snapshots: - '@aws-sdk/checksums@3.1000.24': + '@aws-sdk/checksums@3.1000.28': dependencies: - '@aws-sdk/core': 3.977.4 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.977.8 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/client-eventbridge@3.1101.0': + '@aws-sdk/client-cloudwatch-logs@3.1113.0': dependencies: - '@aws-sdk/core': 3.977.4 - '@aws-sdk/credential-provider-node': 3.972.76 - '@aws-sdk/signature-v4-multi-region': 3.996.43 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/fetch-http-handler': 5.6.13 - '@smithy/node-http-handler': 4.9.13 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.977.8 + '@aws-sdk/credential-provider-node': 3.972.80 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/fetch-http-handler': 5.7.2 + '@smithy/node-http-handler': 4.11.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/client-lambda@3.1101.0': + '@aws-sdk/client-dynamodb@3.1113.0': + dependencies: + '@aws-sdk/core': 3.977.8 + '@aws-sdk/credential-provider-node': 3.972.80 + '@aws-sdk/dynamodb-codec': 3.973.43 + '@aws-sdk/middleware-endpoint-discovery': 3.972.29 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/fetch-http-handler': 5.7.2 + '@smithy/node-http-handler': 4.11.2 + '@smithy/types': 4.17.2 + tslib: 2.8.1 + + '@aws-sdk/client-eventbridge@3.1111.0': dependencies: - '@aws-sdk/core': 3.977.4 - '@aws-sdk/credential-provider-node': 3.972.76 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/fetch-http-handler': 5.6.13 - '@smithy/node-http-handler': 4.9.13 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.977.8 + '@aws-sdk/credential-provider-node': 3.972.80 + '@aws-sdk/signature-v4-multi-region': 3.996.45 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/fetch-http-handler': 5.7.2 + '@smithy/node-http-handler': 4.11.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/client-s3@3.1101.0': - dependencies: - '@aws-sdk/checksums': 3.1000.24 - '@aws-sdk/core': 3.977.4 - '@aws-sdk/credential-provider-node': 3.972.76 - '@aws-sdk/middleware-sdk-s3': 3.972.70 - '@aws-sdk/signature-v4-multi-region': 3.996.43 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/fetch-http-handler': 5.6.13 - '@smithy/node-http-handler': 4.9.13 - '@smithy/types': 4.16.1 + '@aws-sdk/client-eventbridge@3.1113.0': + dependencies: + '@aws-sdk/core': 3.977.8 + '@aws-sdk/credential-provider-node': 3.972.80 + '@aws-sdk/signature-v4-multi-region': 3.996.45 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/fetch-http-handler': 5.7.2 + '@smithy/node-http-handler': 4.11.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/client-ssm@3.1101.0': + '@aws-sdk/client-lambda@3.1111.0': dependencies: - '@aws-sdk/core': 3.977.4 - '@aws-sdk/credential-provider-node': 3.972.76 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/fetch-http-handler': 5.6.13 - '@smithy/node-http-handler': 4.9.13 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.977.8 + '@aws-sdk/credential-provider-node': 3.972.80 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/fetch-http-handler': 5.7.2 + '@smithy/node-http-handler': 4.11.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/core@3.977.4': + '@aws-sdk/client-s3@3.1111.0': + dependencies: + '@aws-sdk/checksums': 3.1000.28 + '@aws-sdk/core': 3.977.8 + '@aws-sdk/credential-provider-node': 3.972.80 + '@aws-sdk/middleware-sdk-s3': 3.972.74 + '@aws-sdk/signature-v4-multi-region': 3.996.45 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/fetch-http-handler': 5.7.2 + '@smithy/node-http-handler': 4.11.2 + '@smithy/types': 4.17.2 + tslib: 2.8.1 + + '@aws-sdk/client-s3@3.1113.0': + dependencies: + '@aws-sdk/checksums': 3.1000.28 + '@aws-sdk/core': 3.977.8 + '@aws-sdk/credential-provider-node': 3.972.80 + '@aws-sdk/middleware-sdk-s3': 3.972.74 + '@aws-sdk/signature-v4-multi-region': 3.996.45 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/fetch-http-handler': 5.7.2 + '@smithy/node-http-handler': 4.11.2 + '@smithy/types': 4.17.2 + tslib: 2.8.1 + + '@aws-sdk/client-sqs@3.1113.0': + dependencies: + '@aws-sdk/core': 3.977.8 + '@aws-sdk/credential-provider-node': 3.972.80 + '@aws-sdk/middleware-sdk-sqs': 3.972.41 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/fetch-http-handler': 5.7.2 + '@smithy/node-http-handler': 4.11.2 + '@smithy/types': 4.17.2 + tslib: 2.8.1 + + '@aws-sdk/client-ssm@3.1111.0': dependencies: - '@aws-sdk/types': 3.974.2 - '@aws-sdk/xml-builder': 3.972.37 + '@aws-sdk/core': 3.977.8 + '@aws-sdk/credential-provider-node': 3.972.80 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/fetch-http-handler': 5.7.2 + '@smithy/node-http-handler': 4.11.2 + '@smithy/types': 4.17.2 + tslib: 2.8.1 + + '@aws-sdk/core@3.977.8': + dependencies: + '@aws-sdk/types': 3.974.4 + '@aws-sdk/xml-builder': 3.972.39 '@aws/lambda-invoke-store': 0.3.0 - '@smithy/core': 3.31.1 - '@smithy/signature-v4': 5.6.12 - '@smithy/types': 4.16.1 + '@smithy/core': 3.33.2 + '@smithy/signature-v4': 5.7.2 + '@smithy/types': 4.17.2 bowser: 2.14.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.972.65': + '@aws-sdk/credential-provider-env@3.972.69': + dependencies: + '@aws-sdk/core': 3.977.8 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.972.71': + dependencies: + '@aws-sdk/core': 3.977.8 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/fetch-http-handler': 5.7.2 + '@smithy/node-http-handler': 4.11.2 + '@smithy/types': 4.17.2 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.973.14': + dependencies: + '@aws-sdk/core': 3.977.8 + '@aws-sdk/credential-provider-env': 3.972.69 + '@aws-sdk/credential-provider-http': 3.972.71 + '@aws-sdk/credential-provider-login': 3.972.76 + '@aws-sdk/credential-provider-process': 3.972.69 + '@aws-sdk/credential-provider-sso': 3.973.13 + '@aws-sdk/credential-provider-web-identity': 3.972.75 + '@aws-sdk/nested-clients': 3.997.43 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/credential-provider-imds': 4.5.2 + '@smithy/types': 4.17.2 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-login@3.972.76': + dependencies: + '@aws-sdk/core': 3.977.8 + '@aws-sdk/nested-clients': 3.997.43 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-node@3.972.80': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.69 + '@aws-sdk/credential-provider-http': 3.972.71 + '@aws-sdk/credential-provider-ini': 3.973.14 + '@aws-sdk/credential-provider-process': 3.972.69 + '@aws-sdk/credential-provider-sso': 3.973.13 + '@aws-sdk/credential-provider-web-identity': 3.972.75 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/credential-provider-imds': 4.5.2 + '@smithy/types': 4.17.2 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-process@3.972.69': dependencies: - '@aws-sdk/core': 3.977.4 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.977.8 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.972.67': + '@aws-sdk/credential-provider-sso@3.973.13': dependencies: - '@aws-sdk/core': 3.977.4 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/fetch-http-handler': 5.6.13 - '@smithy/node-http-handler': 4.9.13 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.977.8 + '@aws-sdk/nested-clients': 3.997.43 + '@aws-sdk/token-providers': 3.1111.0 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.973.10': - dependencies: - '@aws-sdk/core': 3.977.4 - '@aws-sdk/credential-provider-env': 3.972.65 - '@aws-sdk/credential-provider-http': 3.972.67 - '@aws-sdk/credential-provider-login': 3.972.72 - '@aws-sdk/credential-provider-process': 3.972.65 - '@aws-sdk/credential-provider-sso': 3.973.9 - '@aws-sdk/credential-provider-web-identity': 3.972.71 - '@aws-sdk/nested-clients': 3.997.39 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/credential-provider-imds': 4.4.16 - '@smithy/types': 4.16.1 + '@aws-sdk/credential-provider-web-identity@3.972.75': + dependencies: + '@aws-sdk/core': 3.977.8 + '@aws-sdk/nested-clients': 3.997.43 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/credential-provider-login@3.972.72': + '@aws-sdk/dynamodb-codec@3.973.43': dependencies: - '@aws-sdk/core': 3.977.4 - '@aws-sdk/nested-clients': 3.997.39 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.977.8 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/credential-provider-node@3.972.76': - dependencies: - '@aws-sdk/credential-provider-env': 3.972.65 - '@aws-sdk/credential-provider-http': 3.972.67 - '@aws-sdk/credential-provider-ini': 3.973.10 - '@aws-sdk/credential-provider-process': 3.972.65 - '@aws-sdk/credential-provider-sso': 3.973.9 - '@aws-sdk/credential-provider-web-identity': 3.972.71 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/credential-provider-imds': 4.4.16 - '@smithy/types': 4.16.1 + '@aws-sdk/endpoint-cache@3.972.11': + dependencies: + mnemonist: 0.38.3 tslib: 2.8.1 - '@aws-sdk/credential-provider-process@3.972.65': + '@aws-sdk/lib-dynamodb@3.1113.0(@aws-sdk/client-dynamodb@3.1113.0)': dependencies: - '@aws-sdk/core': 3.977.4 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/types': 4.16.1 + '@aws-sdk/client-dynamodb': 3.1113.0 + '@aws-sdk/core': 3.977.8 + '@aws-sdk/util-dynamodb': 3.996.9(@aws-sdk/client-dynamodb@3.1113.0) + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.973.9': + '@aws-sdk/middleware-endpoint-discovery@3.972.29': dependencies: - '@aws-sdk/core': 3.977.4 - '@aws-sdk/nested-clients': 3.997.39 - '@aws-sdk/token-providers': 3.1100.0 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/types': 4.16.1 + '@aws-sdk/endpoint-cache': 3.972.11 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/credential-provider-web-identity@3.972.71': + '@aws-sdk/middleware-sdk-s3@3.972.74': dependencies: - '@aws-sdk/core': 3.977.4 - '@aws-sdk/nested-clients': 3.997.39 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.977.8 + '@aws-sdk/signature-v4-multi-region': 3.996.45 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.972.70': + '@aws-sdk/middleware-sdk-sqs@3.972.41': dependencies: - '@aws-sdk/core': 3.977.4 - '@aws-sdk/signature-v4-multi-region': 3.996.43 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/types': 4.16.1 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.997.39': + '@aws-sdk/nested-clients@3.997.43': dependencies: - '@aws-sdk/core': 3.977.4 - '@aws-sdk/signature-v4-multi-region': 3.996.43 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/fetch-http-handler': 5.6.13 - '@smithy/node-http-handler': 4.9.13 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.977.8 + '@aws-sdk/signature-v4-multi-region': 3.996.45 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/fetch-http-handler': 5.7.2 + '@smithy/node-http-handler': 4.11.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.996.43': + '@aws-sdk/signature-v4-multi-region@3.996.45': dependencies: - '@aws-sdk/types': 3.974.2 - '@smithy/signature-v4': 5.6.12 - '@smithy/types': 4.16.1 + '@aws-sdk/types': 3.974.4 + '@smithy/signature-v4': 5.7.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/token-providers@3.1100.0': + '@aws-sdk/token-providers@3.1111.0': dependencies: - '@aws-sdk/core': 3.977.4 - '@aws-sdk/nested-clients': 3.997.39 - '@aws-sdk/types': 3.974.2 - '@smithy/core': 3.31.1 - '@smithy/types': 4.16.1 + '@aws-sdk/core': 3.977.8 + '@aws-sdk/nested-clients': 3.997.43 + '@aws-sdk/types': 3.974.4 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/types@3.974.2': + '@aws-sdk/types@3.974.4': dependencies: - '@smithy/types': 4.16.1 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@aws-sdk/xml-builder@3.972.37': + '@aws-sdk/util-dynamodb@3.996.9(@aws-sdk/client-dynamodb@3.1113.0)': dependencies: - '@smithy/types': 4.16.1 + '@aws-sdk/client-dynamodb': 3.1113.0 + tslib: 2.8.1 + + '@aws-sdk/xml-builder@3.972.39': + dependencies: + '@smithy/types': 4.17.2 tslib: 2.8.1 '@aws/lambda-invoke-store@0.3.0': {} @@ -4461,7 +4744,7 @@ snapshots: dependencies: '@babel/compat-data': 7.29.7 '@babel/helper-validator-option': 7.29.7 - browserslist: 4.28.7 + browserslist: 4.28.8 lru-cache: 5.1.1 semver: 6.3.1 @@ -4641,157 +4924,157 @@ snapshots: '@esbuild/aix-ppc64@0.25.12': optional: true - '@esbuild/aix-ppc64@0.28.1': + '@esbuild/aix-ppc64@0.28.2': optional: true '@esbuild/android-arm64@0.25.12': optional: true - '@esbuild/android-arm64@0.28.1': + '@esbuild/android-arm64@0.28.2': optional: true '@esbuild/android-arm@0.25.12': optional: true - '@esbuild/android-arm@0.28.1': + '@esbuild/android-arm@0.28.2': optional: true '@esbuild/android-x64@0.25.12': optional: true - '@esbuild/android-x64@0.28.1': + '@esbuild/android-x64@0.28.2': optional: true '@esbuild/darwin-arm64@0.25.12': optional: true - '@esbuild/darwin-arm64@0.28.1': + '@esbuild/darwin-arm64@0.28.2': optional: true '@esbuild/darwin-x64@0.25.12': optional: true - '@esbuild/darwin-x64@0.28.1': + '@esbuild/darwin-x64@0.28.2': optional: true '@esbuild/freebsd-arm64@0.25.12': optional: true - '@esbuild/freebsd-arm64@0.28.1': + '@esbuild/freebsd-arm64@0.28.2': optional: true '@esbuild/freebsd-x64@0.25.12': optional: true - '@esbuild/freebsd-x64@0.28.1': + '@esbuild/freebsd-x64@0.28.2': optional: true '@esbuild/linux-arm64@0.25.12': optional: true - '@esbuild/linux-arm64@0.28.1': + '@esbuild/linux-arm64@0.28.2': optional: true '@esbuild/linux-arm@0.25.12': optional: true - '@esbuild/linux-arm@0.28.1': + '@esbuild/linux-arm@0.28.2': optional: true '@esbuild/linux-ia32@0.25.12': optional: true - '@esbuild/linux-ia32@0.28.1': + '@esbuild/linux-ia32@0.28.2': optional: true '@esbuild/linux-loong64@0.25.12': optional: true - '@esbuild/linux-loong64@0.28.1': + '@esbuild/linux-loong64@0.28.2': optional: true '@esbuild/linux-mips64el@0.25.12': optional: true - '@esbuild/linux-mips64el@0.28.1': + '@esbuild/linux-mips64el@0.28.2': optional: true '@esbuild/linux-ppc64@0.25.12': optional: true - '@esbuild/linux-ppc64@0.28.1': + '@esbuild/linux-ppc64@0.28.2': optional: true '@esbuild/linux-riscv64@0.25.12': optional: true - '@esbuild/linux-riscv64@0.28.1': + '@esbuild/linux-riscv64@0.28.2': optional: true '@esbuild/linux-s390x@0.25.12': optional: true - '@esbuild/linux-s390x@0.28.1': + '@esbuild/linux-s390x@0.28.2': optional: true '@esbuild/linux-x64@0.25.12': optional: true - '@esbuild/linux-x64@0.28.1': + '@esbuild/linux-x64@0.28.2': optional: true '@esbuild/netbsd-arm64@0.25.12': optional: true - '@esbuild/netbsd-arm64@0.28.1': + '@esbuild/netbsd-arm64@0.28.2': optional: true '@esbuild/netbsd-x64@0.25.12': optional: true - '@esbuild/netbsd-x64@0.28.1': + '@esbuild/netbsd-x64@0.28.2': optional: true '@esbuild/openbsd-arm64@0.25.12': optional: true - '@esbuild/openbsd-arm64@0.28.1': + '@esbuild/openbsd-arm64@0.28.2': optional: true '@esbuild/openbsd-x64@0.25.12': optional: true - '@esbuild/openbsd-x64@0.28.1': + '@esbuild/openbsd-x64@0.28.2': optional: true '@esbuild/openharmony-arm64@0.25.12': optional: true - '@esbuild/openharmony-arm64@0.28.1': + '@esbuild/openharmony-arm64@0.28.2': optional: true '@esbuild/sunos-x64@0.25.12': optional: true - '@esbuild/sunos-x64@0.28.1': + '@esbuild/sunos-x64@0.28.2': optional: true '@esbuild/win32-arm64@0.25.12': optional: true - '@esbuild/win32-arm64@0.28.1': + '@esbuild/win32-arm64@0.28.2': optional: true '@esbuild/win32-ia32@0.25.12': optional: true - '@esbuild/win32-ia32@0.28.1': + '@esbuild/win32-ia32@0.28.2': optional: true '@esbuild/win32-x64@0.25.12': optional: true - '@esbuild/win32-x64@0.28.1': + '@esbuild/win32-x64@0.28.2': optional: true '@eslint-community/eslint-utils@4.10.1(eslint@9.39.5(supports-color@8.1.1))': @@ -4902,7 +5185,7 @@ snapshots: jest-util: 30.4.1 slash: 3.0.0 - '@jest/core@29.7.0(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3))': + '@jest/core@29.7.0(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0(supports-color@8.1.1) @@ -4916,7 +5199,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + jest-config: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -4946,13 +5229,6 @@ snapshots: '@types/node': 25.9.5 jest-mock: 29.7.0 - '@jest/environment@30.4.1': - dependencies: - '@jest/fake-timers': 30.4.1 - '@jest/types': 30.4.1 - '@types/node': 25.9.5 - jest-mock: 30.4.1 - '@jest/expect-utils@29.7.0': dependencies: jest-get-type: 29.6.3 @@ -4968,13 +5244,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@jest/expect@30.4.1(supports-color@8.1.1)': - dependencies: - expect: 30.4.1 - jest-snapshot: 30.4.1(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - '@jest/fake-timers@29.7.0': dependencies: '@jest/types': 29.6.3 @@ -4984,15 +5253,6 @@ snapshots: jest-mock: 29.7.0 jest-util: 29.7.0 - '@jest/fake-timers@30.4.1': - dependencies: - '@jest/types': 30.4.1 - '@sinonjs/fake-timers': 15.4.0 - '@types/node': 25.9.5 - jest-message-util: 30.4.1 - jest-mock: 30.4.1 - jest-util: 30.4.1 - '@jest/get-type@30.1.0': {} '@jest/globals@29.7.0(supports-color@8.1.1)': @@ -5004,15 +5264,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@jest/globals@30.4.1(supports-color@8.1.1)': - dependencies: - '@jest/environment': 30.4.1 - '@jest/expect': 30.4.1(supports-color@8.1.1) - '@jest/types': 30.4.1 - jest-mock: 30.4.1 - transitivePeerDependencies: - - supports-color - '@jest/pattern@30.4.0': dependencies: '@types/node': 25.9.5 @@ -5083,13 +5334,6 @@ snapshots: dependencies: '@sinclair/typebox': 0.34.52 - '@jest/snapshot-utils@30.4.1': - dependencies: - '@jest/types': 30.4.1 - chalk: 4.1.2 - graceful-fs: 4.2.11 - natural-compare: 1.4.0 - '@jest/source-map@29.6.3': dependencies: '@jridgewell/trace-mapping': 0.3.31 @@ -5199,7 +5443,7 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@napi-rs/wasm-runtime@1.2.2(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: '@emnapi/core': 1.10.0 '@emnapi/runtime': 1.10.0 @@ -5218,6 +5462,8 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 + '@pinojs/redact@0.4.0': {} + '@pkgjs/parseargs@0.11.0': optional: true @@ -5248,36 +5494,36 @@ snapshots: '@sinonjs/commons': 3.0.1 type-detect: 4.1.0 - '@smithy/core@3.31.1': + '@smithy/core@3.33.2': dependencies: - '@smithy/types': 4.16.1 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@smithy/credential-provider-imds@4.4.16': + '@smithy/credential-provider-imds@4.5.2': dependencies: - '@smithy/core': 3.31.1 - '@smithy/types': 4.16.1 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@smithy/fetch-http-handler@5.6.13': + '@smithy/fetch-http-handler@5.7.2': dependencies: - '@smithy/core': 3.31.1 - '@smithy/types': 4.16.1 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@smithy/node-http-handler@4.9.13': + '@smithy/node-http-handler@4.11.2': dependencies: - '@smithy/core': 3.31.1 - '@smithy/types': 4.16.1 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@smithy/signature-v4@5.6.12': + '@smithy/signature-v4@5.7.2': dependencies: - '@smithy/core': 3.31.1 - '@smithy/types': 4.16.1 + '@smithy/core': 3.33.2 + '@smithy/types': 4.17.2 tslib: 2.8.1 - '@smithy/types@4.16.1': + '@smithy/types@4.17.2': dependencies: tslib: 2.8.1 @@ -5288,9 +5534,9 @@ snapshots: '@standard-schema/spec@1.1.0': {} - '@stylistic/eslint-plugin-ts@4.4.1(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)': + '@stylistic/eslint-plugin-ts@4.4.1(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': dependencies: - '@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) eslint: 9.39.5(supports-color@8.1.1) eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -5298,9 +5544,9 @@ snapshots: - supports-color - typescript - '@stylistic/eslint-plugin@3.1.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)': + '@stylistic/eslint-plugin@3.1.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': dependencies: - '@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) eslint: 9.39.5(supports-color@8.1.1) eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -5312,7 +5558,7 @@ snapshots: '@tootallnate/once@2.0.1': {} - '@tsconfig/node10@1.0.12': {} + '@tsconfig/node10@1.0.13': {} '@tsconfig/node12@1.0.11': {} @@ -5320,24 +5566,24 @@ snapshots: '@tsconfig/node16@1.0.4': {} - '@tsconfig/node22@22.0.5': {} + '@tsconfig/node22@22.0.6': {} - '@turbo/darwin-64@2.10.8': + '@turbo/darwin-64@2.10.5': optional: true - '@turbo/darwin-arm64@2.10.8': + '@turbo/darwin-arm64@2.10.5': optional: true - '@turbo/linux-64@2.10.8': + '@turbo/linux-64@2.10.5': optional: true - '@turbo/linux-arm64@2.10.8': + '@turbo/linux-arm64@2.10.5': optional: true - '@turbo/windows-64@2.10.8': + '@turbo/windows-64@2.10.5': optional: true - '@turbo/windows-arm64@2.10.8': + '@turbo/windows-arm64@2.10.5': optional: true '@tybys/wasm-util@0.10.3': @@ -5421,7 +5667,7 @@ snapshots: '@types/qs@6.15.1': {} - '@types/semver@7.8.0': {} + '@types/semver@7.7.1': {} '@types/sinon@17.0.4': dependencies: @@ -5441,30 +5687,30 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) + '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) '@typescript-eslint/scope-manager': 8.65.0 - '@typescript-eslint/type-utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) - '@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) + '@typescript-eslint/type-utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) '@typescript-eslint/visitor-keys': 8.65.0 eslint: 9.39.5(supports-color@8.1.1) ignore: 7.0.6 natural-compare: 1.4.0 - ts-api-utils: 2.5.0(typescript@5.9.3) - typescript: 5.9.3 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': + '@typescript-eslint/eslint-plugin@8.67.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.65.0 - '@typescript-eslint/type-utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) - '@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.65.0 + '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.67.0 + '@typescript-eslint/type-utils': 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.67.0 eslint: 9.39.5(supports-color@8.1.1) ignore: 7.0.6 natural-compare: 1.4.0 @@ -5473,43 +5719,31 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)': + '@typescript-eslint/parser@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': dependencies: - '@typescript-eslint/scope-manager': 8.65.0 - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/typescript-estree': 8.65.0(supports-color@8.1.1)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.65.0 - debug: 4.4.3(supports-color@8.1.1) - eslint: 9.39.5(supports-color@8.1.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.65.0 - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/typescript-estree': 8.65.0(supports-color@8.1.1)(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.65.0 + '@typescript-eslint/scope-manager': 8.67.0 + '@typescript-eslint/types': 8.67.0 + '@typescript-eslint/typescript-estree': 8.67.0(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.67.0 debug: 4.4.3(supports-color@8.1.1) eslint: 9.39.5(supports-color@8.1.1) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.65.0(supports-color@8.1.1)(typescript@5.9.3)': + '@typescript-eslint/project-service@8.65.0(supports-color@8.1.1)(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.65.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.65.0(typescript@6.0.3) '@typescript-eslint/types': 8.65.0 debug: 4.4.3(supports-color@8.1.1) - typescript: 5.9.3 + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.65.0(supports-color@8.1.1)(typescript@6.0.3)': + '@typescript-eslint/project-service@8.67.0(supports-color@8.1.1)(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.65.0(typescript@6.0.3) - '@typescript-eslint/types': 8.65.0 + '@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.3) + '@typescript-eslint/types': 8.67.0 debug: 4.4.3(supports-color@8.1.1) typescript: 6.0.3 transitivePeerDependencies: @@ -5520,31 +5754,36 @@ snapshots: '@typescript-eslint/types': 8.65.0 '@typescript-eslint/visitor-keys': 8.65.0 - '@typescript-eslint/tsconfig-utils@8.65.0(typescript@5.9.3)': + '@typescript-eslint/scope-manager@8.67.0': dependencies: - typescript: 5.9.3 + '@typescript-eslint/types': 8.67.0 + '@typescript-eslint/visitor-keys': 8.67.0 '@typescript-eslint/tsconfig-utils@8.65.0(typescript@6.0.3)': dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.67.0(typescript@6.0.3)': + dependencies: + typescript: 6.0.3 + + '@typescript-eslint/type-utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': dependencies: '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/typescript-estree': 8.65.0(supports-color@8.1.1)(typescript@5.9.3) - '@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.65.0(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) debug: 4.4.3(supports-color@8.1.1) eslint: 9.39.5(supports-color@8.1.1) - ts-api-utils: 2.5.0(typescript@5.9.3) - typescript: 5.9.3 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': dependencies: - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/typescript-estree': 8.65.0(supports-color@8.1.1)(typescript@6.0.3) - '@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/types': 8.67.0 + '@typescript-eslint/typescript-estree': 8.67.0(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) debug: 4.4.3(supports-color@8.1.1) eslint: 9.39.5(supports-color@8.1.1) ts-api-utils: 2.5.0(typescript@6.0.3) @@ -5554,27 +5793,29 @@ snapshots: '@typescript-eslint/types@8.65.0': {} - '@typescript-eslint/typescript-estree@8.65.0(supports-color@8.1.1)(typescript@5.9.3)': + '@typescript-eslint/types@8.67.0': {} + + '@typescript-eslint/typescript-estree@8.65.0(supports-color@8.1.1)(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.65.0(supports-color@8.1.1)(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.65.0(typescript@5.9.3) + '@typescript-eslint/project-service': 8.65.0(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.65.0(typescript@6.0.3) '@typescript-eslint/types': 8.65.0 '@typescript-eslint/visitor-keys': 8.65.0 debug: 4.4.3(supports-color@8.1.1) minimatch: 10.2.6 semver: 7.8.5 tinyglobby: 0.2.17 - ts-api-utils: 2.5.0(typescript@5.9.3) - typescript: 5.9.3 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@8.65.0(supports-color@8.1.1)(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.67.0(supports-color@8.1.1)(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.65.0(supports-color@8.1.1)(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.65.0(typescript@6.0.3) - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/visitor-keys': 8.65.0 + '@typescript-eslint/project-service': 8.67.0(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.3) + '@typescript-eslint/types': 8.67.0 + '@typescript-eslint/visitor-keys': 8.67.0 debug: 4.4.3(supports-color@8.1.1) minimatch: 10.2.6 semver: 7.8.5 @@ -5584,23 +5825,23 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)': + '@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': dependencies: '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@8.1.1)) '@typescript-eslint/scope-manager': 8.65.0 '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/typescript-estree': 8.65.0(supports-color@8.1.1)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.65.0(supports-color@8.1.1)(typescript@6.0.3) eslint: 9.39.5(supports-color@8.1.1) - typescript: 5.9.3 + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': + '@typescript-eslint/utils@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)': dependencies: '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@8.1.1)) - '@typescript-eslint/scope-manager': 8.65.0 - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/typescript-estree': 8.65.0(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.67.0 + '@typescript-eslint/types': 8.67.0 + '@typescript-eslint/typescript-estree': 8.67.0(supports-color@8.1.1)(typescript@6.0.3) eslint: 9.39.5(supports-color@8.1.1) typescript: 6.0.3 transitivePeerDependencies: @@ -5611,6 +5852,11 @@ snapshots: '@typescript-eslint/types': 8.65.0 eslint-visitor-keys: 5.0.1 + '@typescript-eslint/visitor-keys@8.67.0': + dependencies: + '@typescript-eslint/types': 8.67.0 + eslint-visitor-keys: 5.0.1 + '@ungap/structured-clone@1.3.3': {} '@unrs/resolver-binding-android-arm-eabi@1.12.2': @@ -5671,7 +5917,7 @@ snapshots: dependencies: '@emnapi/core': 1.10.0 '@emnapi/runtime': 1.10.0 - '@napi-rs/wasm-runtime': 1.2.2(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': @@ -5740,7 +5986,7 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.2.2: {} + ansi-regex@6.3.0: {} ansi-styles@4.3.0: dependencies: @@ -5836,6 +6082,8 @@ snapshots: asynckit@0.4.0: {} + atomic-sleep@1.0.0: {} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 @@ -5853,7 +6101,7 @@ snapshots: sinon: 18.0.1 tslib: 2.8.1 - axe-core@4.12.1: {} + axe-core@4.13.0: {} axios@1.19.0(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1): dependencies: @@ -5880,20 +6128,6 @@ snapshots: transitivePeerDependencies: - supports-color - babel-jest@30.4.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1): - dependencies: - '@babel/core': 7.29.7(supports-color@8.1.1) - '@jest/transform': 30.4.1(supports-color@8.1.1) - '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 7.0.1(supports-color@8.1.1) - babel-preset-jest: 30.4.0(@babel/core@7.29.7(supports-color@8.1.1)) - chalk: 4.1.2 - graceful-fs: 4.2.11 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color - optional: true - babel-plugin-istanbul@6.1.1(supports-color@8.1.1): dependencies: '@babel/helper-plugin-utils': 7.29.7 @@ -5921,11 +6155,6 @@ snapshots: '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.28.0 - babel-plugin-jest-hoist@30.4.0: - dependencies: - '@types/babel__core': 7.20.5 - optional: true - babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.7(supports-color@8.1.1)): dependencies: '@babel/core': 7.29.7(supports-color@8.1.1) @@ -5951,18 +6180,11 @@ snapshots: babel-plugin-jest-hoist: 29.6.3 babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7(supports-color@8.1.1)) - babel-preset-jest@30.4.0(@babel/core@7.29.7(supports-color@8.1.1)): - dependencies: - '@babel/core': 7.29.7(supports-color@8.1.1) - babel-plugin-jest-hoist: 30.4.0 - babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7(supports-color@8.1.1)) - optional: true - balanced-match@1.0.2: {} balanced-match@4.0.4: {} - baseline-browser-mapping@2.11.11: {} + baseline-browser-mapping@2.11.14: {} bowser@2.14.1: {} @@ -5983,13 +6205,13 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.28.7: + browserslist@4.28.8: dependencies: - baseline-browser-mapping: 2.11.11 - caniuse-lite: 1.0.30001806 - electron-to-chromium: 1.5.399 - node-releases: 2.0.51 - update-browserslist-db: 1.2.3(browserslist@4.28.7) + baseline-browser-mapping: 2.11.14 + caniuse-lite: 1.0.30001809 + electron-to-chromium: 1.5.408 + node-releases: 2.0.53 + update-browserslist-db: 1.3.1(browserslist@4.28.8) bs-logger@0.2.6: dependencies: @@ -6032,7 +6254,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001806: {} + caniuse-lite@1.0.30001809: {} chai@6.2.2: {} @@ -6096,7 +6318,7 @@ snapshots: dependencies: delayed-stream: 1.0.0 - comment-parser@1.4.7: {} + comment-parser@1.4.8: {} concat-map@0.0.1: {} @@ -6104,17 +6326,17 @@ snapshots: convert-source-map@2.0.0: {} - core-js-compat@3.49.0: + core-js-compat@3.50.0: dependencies: - browserslist: 4.28.7 + browserslist: 4.28.8 - create-jest@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)): + create-jest@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + jest-config: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -6123,13 +6345,13 @@ snapshots: - supports-color - ts-node - create-jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)): + create-jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + jest-config: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -6258,7 +6480,7 @@ snapshots: dependencies: safe-buffer: 5.2.1 - electron-to-chromium@1.5.399: {} + electron-to-chromium@1.5.408: {} emittery@0.13.1: {} @@ -6418,34 +6640,34 @@ snapshots: '@esbuild/win32-ia32': 0.25.12 '@esbuild/win32-x64': 0.25.12 - esbuild@0.28.1: + esbuild@0.28.2: optionalDependencies: - '@esbuild/aix-ppc64': 0.28.1 - '@esbuild/android-arm': 0.28.1 - '@esbuild/android-arm64': 0.28.1 - '@esbuild/android-x64': 0.28.1 - '@esbuild/darwin-arm64': 0.28.1 - '@esbuild/darwin-x64': 0.28.1 - '@esbuild/freebsd-arm64': 0.28.1 - '@esbuild/freebsd-x64': 0.28.1 - '@esbuild/linux-arm': 0.28.1 - '@esbuild/linux-arm64': 0.28.1 - '@esbuild/linux-ia32': 0.28.1 - '@esbuild/linux-loong64': 0.28.1 - '@esbuild/linux-mips64el': 0.28.1 - '@esbuild/linux-ppc64': 0.28.1 - '@esbuild/linux-riscv64': 0.28.1 - '@esbuild/linux-s390x': 0.28.1 - '@esbuild/linux-x64': 0.28.1 - '@esbuild/netbsd-arm64': 0.28.1 - '@esbuild/netbsd-x64': 0.28.1 - '@esbuild/openbsd-arm64': 0.28.1 - '@esbuild/openbsd-x64': 0.28.1 - '@esbuild/openharmony-arm64': 0.28.1 - '@esbuild/sunos-x64': 0.28.1 - '@esbuild/win32-arm64': 0.28.1 - '@esbuild/win32-ia32': 0.28.1 - '@esbuild/win32-x64': 0.28.1 + '@esbuild/aix-ppc64': 0.28.2 + '@esbuild/android-arm': 0.28.2 + '@esbuild/android-arm64': 0.28.2 + '@esbuild/android-x64': 0.28.2 + '@esbuild/darwin-arm64': 0.28.2 + '@esbuild/darwin-x64': 0.28.2 + '@esbuild/freebsd-arm64': 0.28.2 + '@esbuild/freebsd-x64': 0.28.2 + '@esbuild/linux-arm': 0.28.2 + '@esbuild/linux-arm64': 0.28.2 + '@esbuild/linux-ia32': 0.28.2 + '@esbuild/linux-loong64': 0.28.2 + '@esbuild/linux-mips64el': 0.28.2 + '@esbuild/linux-ppc64': 0.28.2 + '@esbuild/linux-riscv64': 0.28.2 + '@esbuild/linux-s390x': 0.28.2 + '@esbuild/linux-x64': 0.28.2 + '@esbuild/netbsd-arm64': 0.28.2 + '@esbuild/netbsd-x64': 0.28.2 + '@esbuild/openbsd-arm64': 0.28.2 + '@esbuild/openbsd-x64': 0.28.2 + '@esbuild/openharmony-arm64': 0.28.2 + '@esbuild/sunos-x64': 0.28.2 + '@esbuild/win32-arm64': 0.28.2 + '@esbuild/win32-ia32': 0.28.2 + '@esbuild/win32-x64': 0.28.2 escalade@3.2.0: {} @@ -6463,19 +6685,19 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-airbnb-extended@2.3.3(@stylistic/eslint-plugin@3.1.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.5(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.5(supports-color@8.1.1)))(eslint-plugin-react-hooks@7.1.1(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint-plugin-react@7.37.5(eslint@9.39.5(supports-color@8.1.1)))(eslint@9.39.5(supports-color@8.1.1))(typescript-eslint@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)): + eslint-config-airbnb-extended@2.3.3(@stylistic/eslint-plugin@3.1.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint-import-resolver-typescript@4.4.5(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.5(supports-color@8.1.1)))(eslint-plugin-react-hooks@7.1.1(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint-plugin-react@7.37.5(eslint@9.39.5(supports-color@8.1.1)))(eslint@9.39.5(supports-color@8.1.1))(typescript-eslint@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3)): dependencies: confusing-browser-globals: 1.0.11 eslint: 9.39.5(supports-color@8.1.1) globals: 16.5.0 optionalDependencies: - '@stylistic/eslint-plugin': 3.1.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) - eslint-import-resolver-typescript: 4.4.5(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1) - eslint-plugin-import-x: 4.17.1(@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1) + '@stylistic/eslint-plugin': 3.1.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + eslint-import-resolver-typescript: 4.4.5(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1) + eslint-plugin-import-x: 4.17.1(@typescript-eslint/utils@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.5(supports-color@8.1.1)) eslint-plugin-react: 7.37.5(eslint@9.39.5(supports-color@8.1.1)) eslint-plugin-react-hooks: 7.1.1(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1) - typescript-eslint: 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) + typescript-eslint: 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) eslint-config-prettier@10.1.8(eslint@9.39.5(supports-color@8.1.1)): dependencies: @@ -6483,23 +6705,23 @@ snapshots: eslint-import-context@0.1.9(unrs-resolver@1.12.2): dependencies: - get-tsconfig: 4.14.1 + get-tsconfig: 4.14.2 stable-hash-x: 0.2.0 optionalDependencies: unrs-resolver: 1.12.2 - eslint-import-resolver-typescript@4.4.5(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1): + eslint-import-resolver-typescript@4.4.5(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1): dependencies: debug: 4.4.3(supports-color@8.1.1) eslint: 9.39.5(supports-color@8.1.1) eslint-import-context: 0.1.9(unrs-resolver@1.12.2) - get-tsconfig: 4.14.1 + get-tsconfig: 4.14.2 is-bun-module: 2.0.0 stable-hash-x: 0.2.0 tinyglobby: 0.2.17 unrs-resolver: 1.12.2 optionalDependencies: - eslint-plugin-import-x: 4.17.1(@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1) + eslint-plugin-import-x: 4.17.1(@typescript-eslint/utils@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -6507,10 +6729,10 @@ snapshots: dependencies: htmlparser2: 10.1.0 - eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1): + eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1): dependencies: - '@typescript-eslint/types': 8.65.0 - comment-parser: 1.4.7 + '@typescript-eslint/types': 8.67.0 + comment-parser: 1.4.8 debug: 4.4.3(supports-color@8.1.1) eslint: 9.39.5(supports-color@8.1.1) eslint-import-context: 0.1.9(unrs-resolver@1.12.2) @@ -6520,18 +6742,18 @@ snapshots: stable-hash-x: 0.2.0 unrs-resolver: 1.12.2 optionalDependencies: - '@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) transitivePeerDependencies: - supports-color - eslint-plugin-jest@29.16.0(@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3))(eslint@9.39.5(supports-color@8.1.1))(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)))(supports-color@8.1.1)(typescript@5.9.3): + eslint-plugin-jest@29.16.1(@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(supports-color@8.1.1)(typescript@6.0.3): dependencies: - '@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) eslint: 9.39.5(supports-color@8.1.1) optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) - jest: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) - typescript: 5.9.3 + '@typescript-eslint/eslint-plugin': 8.65.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + jest: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) + typescript: 6.0.3 transitivePeerDependencies: - supports-color @@ -6546,7 +6768,7 @@ snapshots: array-includes: 3.1.9 array.prototype.flatmap: 1.3.3 ast-types-flow: 0.0.8 - axe-core: 4.12.1 + axe-core: 4.13.0 axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 @@ -6619,7 +6841,7 @@ snapshots: minimatch: 10.2.6 scslre: 0.3.0 semver: 7.7.4 - typescript: 5.9.3 + typescript: 6.0.3 eslint-plugin-sort-destructure-keys@2.0.0(eslint@9.39.5(supports-color@8.1.1)): dependencies: @@ -6634,7 +6856,7 @@ snapshots: change-case: 5.4.4 ci-info: 4.4.0 clean-regexp: 1.0.0 - core-js-compat: 3.49.0 + core-js-compat: 3.50.0 eslint: 9.39.5(supports-color@8.1.1) esquery: 1.7.0 find-up-simple: 1.0.1 @@ -6888,7 +7110,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 - get-tsconfig@4.14.1: + get-tsconfig@4.14.2: dependencies: resolve-pkg-maps: 1.0.0 @@ -6922,7 +7144,7 @@ snapshots: globals@16.5.0: {} - globals@17.9.0: {} + globals@17.11.0: {} globalthis@1.0.4: dependencies: @@ -7265,16 +7487,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)): + jest-cli@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)): dependencies: - '@jest/core': 29.7.0(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + '@jest/core': 29.7.0(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + create-jest: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + jest-config: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.3 @@ -7284,16 +7506,16 @@ snapshots: - supports-color - ts-node - jest-cli@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)): + jest-cli@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)): dependencies: - '@jest/core': 29.7.0(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + '@jest/core': 29.7.0(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + create-jest: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + jest-config: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.3 @@ -7303,7 +7525,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)): + jest-config@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)): dependencies: '@babel/core': 7.29.7(supports-color@8.1.1) '@jest/test-sequencer': 29.7.0 @@ -7329,12 +7551,12 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 24.13.3 - ts-node: 10.9.2(@types/node@24.13.3)(typescript@5.9.3) + ts-node: 10.9.2(@types/node@25.9.5)(typescript@6.0.3) transitivePeerDependencies: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)): + jest-config@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)): dependencies: '@babel/core': 7.29.7(supports-color@8.1.1) '@jest/test-sequencer': 29.7.0 @@ -7360,7 +7582,7 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 25.9.5 - ts-node: 10.9.2(@types/node@24.13.3)(typescript@5.9.3) + ts-node: 10.9.2(@types/node@25.9.5)(typescript@6.0.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -7448,13 +7670,13 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - jest-html-reporter@4.4.0(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)))(supports-color@8.1.1): + jest-html-reporter@4.4.0(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(supports-color@8.1.1): dependencies: '@jest/reporters': 30.4.1(supports-color@8.1.1) '@jest/test-result': 30.4.1 '@jest/types': 30.4.1 dateformat: 3.0.2 - jest: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + jest: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) mkdirp: 1.0.4 strip-ansi: 6.0.1 xmlbuilder: 15.0.0 @@ -7506,19 +7728,19 @@ snapshots: slash: 3.0.0 stack-utils: 2.0.6 - jest-mock-extended@3.0.7(jest@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)))(typescript@5.9.3): + jest-mock-extended@3.0.7(jest@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(typescript@5.9.3): dependencies: - jest: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + jest: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) ts-essentials: 10.2.1(typescript@5.9.3) typescript: 5.9.3 - jest-mock-extended@4.0.1(@jest/globals@30.4.1(supports-color@8.1.1))(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)))(typescript@5.9.3): + jest-mock-extended@4.0.1(@jest/globals@29.7.0(supports-color@8.1.1))(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(typescript@6.0.3): dependencies: - '@jest/globals': 30.4.1(supports-color@8.1.1) - jest: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + '@jest/globals': 29.7.0(supports-color@8.1.1) + jest: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) lodash.isequal: 4.5.0 - ts-essentials: 10.2.1(typescript@5.9.3) - typescript: 5.9.3 + ts-essentials: 10.2.1(typescript@6.0.3) + typescript: 6.0.3 jest-mock@29.7.0: dependencies: @@ -7529,7 +7751,7 @@ snapshots: jest-mock@30.4.1: dependencies: '@jest/types': 30.4.1 - '@types/node': 25.9.5 + '@types/node': 24.13.3 jest-util: 30.4.1 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -7637,32 +7859,6 @@ snapshots: transitivePeerDependencies: - supports-color - jest-snapshot@30.4.1(supports-color@8.1.1): - dependencies: - '@babel/core': 7.29.7(supports-color@8.1.1) - '@babel/generator': 7.29.8 - '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) - '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) - '@babel/types': 7.29.8 - '@jest/expect-utils': 30.4.1 - '@jest/get-type': 30.1.0 - '@jest/snapshot-utils': 30.4.1 - '@jest/transform': 30.4.1(supports-color@8.1.1) - '@jest/types': 30.4.1 - babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7(supports-color@8.1.1)) - chalk: 4.1.2 - expect: 30.4.1 - graceful-fs: 4.2.11 - jest-diff: 30.4.1 - jest-matcher-utils: 30.4.1 - jest-message-util: 30.4.1 - jest-util: 30.4.1 - pretty-format: 30.4.1 - semver: 7.8.5 - synckit: 0.11.13 - transitivePeerDependencies: - - supports-color - jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 @@ -7716,24 +7912,24 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)): + jest@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)): dependencies: - '@jest/core': 29.7.0(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + '@jest/core': 29.7.0(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + jest-cli: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros - supports-color - ts-node - jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)): + jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)): dependencies: - '@jest/core': 29.7.0(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + '@jest/core': 29.7.0(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + jest-cli: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -7779,7 +7975,7 @@ snapshots: whatwg-encoding: 2.0.0 whatwg-mimetype: 3.0.0 whatwg-url: 11.0.0 - ws: 8.21.1 + ws: 8.21.3 xml-name-validator: 4.0.0 transitivePeerDependencies: - bufferutil @@ -7961,6 +8157,10 @@ snapshots: mkdirp@1.0.4: {} + mnemonist@0.38.3: + dependencies: + obliterator: 1.6.1 + ms@2.1.3: {} napi-postinstall@0.3.4: {} @@ -7987,7 +8187,7 @@ snapshots: node-int64@0.4.0: {} - node-releases@2.0.51: {} + node-releases@2.0.53: {} normalize-path@3.0.0: {} @@ -8033,6 +8233,10 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.2 + obliterator@1.6.1: {} + + on-exit-leak-free@2.1.2: {} + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -8117,6 +8321,26 @@ snapshots: picomatch@4.0.5: {} + pino-abstract-transport@3.0.0: + dependencies: + split2: 4.2.0 + + pino-std-serializers@7.1.0: {} + + pino@10.3.1: + dependencies: + '@pinojs/redact': 0.4.0 + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 3.0.0 + pino-std-serializers: 7.1.0 + process-warning: 5.1.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.1 + thread-stream: 4.2.0 + pirates@4.0.7: {} pkg-dir@4.2.0: @@ -8148,6 +8372,8 @@ snapshots: react-is-18: react-is@18.3.1 react-is-19: react-is@19.2.8 + process-warning@5.1.0: {} + prompts@2.4.2: dependencies: kleur: 3.0.3 @@ -8178,6 +8404,8 @@ snapshots: queue-microtask@1.2.3: {} + quick-format-unescaped@4.0.4: {} + react-is@16.13.1: {} react-is@18.3.1: {} @@ -8190,6 +8418,10 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 + real-require@0.2.0: {} + + real-require@1.0.0: {} + refa@0.12.1: dependencies: '@eslint-community/regexpp': 4.12.2 @@ -8381,6 +8613,10 @@ snapshots: slash@3.0.0: {} + sonic-boom@4.2.1: + dependencies: + atomic-sleep: 1.0.0 + source-map-support@0.5.13: dependencies: buffer-from: 1.1.2 @@ -8388,6 +8624,8 @@ snapshots: source-map@0.6.1: {} + split2@4.2.0: {} + sprintf-js@1.0.3: {} stable-hash-x@0.2.0: {} @@ -8481,7 +8719,7 @@ snapshots: strip-ansi@7.2.0: dependencies: - ansi-regex: 6.2.2 + ansi-regex: 6.3.0 strip-bom@4.0.0: {} @@ -8515,6 +8753,10 @@ snapshots: text-hex@1.0.0: {} + thread-stream@4.2.0: + dependencies: + real-require: 1.0.0 + tinyglobby@0.2.17: dependencies: fdir: 6.5.0(picomatch@4.0.5) @@ -8541,10 +8783,6 @@ snapshots: triple-beam@1.4.1: {} - ts-api-utils@2.5.0(typescript@5.9.3): - dependencies: - typescript: 5.9.3 - ts-api-utils@2.5.0(typescript@6.0.3): dependencies: typescript: 6.0.3 @@ -8553,33 +8791,58 @@ snapshots: optionalDependencies: typescript: 5.9.3 - ts-jest@29.4.12(@babel/core@7.29.7(supports-color@8.1.1))(@jest/transform@30.4.1(supports-color@8.1.1))(@jest/types@30.4.1)(babel-jest@30.4.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(esbuild@0.25.12)(jest-util@30.4.1)(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)))(typescript@5.9.3): + ts-essentials@10.2.1(typescript@6.0.3): + optionalDependencies: + typescript: 6.0.3 + + ts-jest@29.4.12(@babel/core@7.29.7(supports-color@8.1.1))(@jest/transform@30.4.1(supports-color@8.1.1))(@jest/types@30.4.1)(babel-jest@29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(esbuild@0.25.12)(jest-util@30.4.1)(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(typescript@6.0.3): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 handlebars: 4.7.9 - jest: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + jest: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.8.5 type-fest: 4.41.0 - typescript: 5.9.3 + typescript: 6.0.3 yargs-parser: 21.1.1 optionalDependencies: '@babel/core': 7.29.7(supports-color@8.1.1) '@jest/transform': 30.4.1(supports-color@8.1.1) '@jest/types': 30.4.1 - babel-jest: 30.4.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + babel-jest: 29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) esbuild: 0.25.12 jest-util: 30.4.1 - ts-jest@29.4.12(@babel/core@7.29.7(supports-color@8.1.1))(@jest/transform@30.4.1(supports-color@8.1.1))(@jest/types@30.4.1)(babel-jest@30.4.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(esbuild@0.28.1)(jest-util@30.4.1)(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)))(typescript@6.0.3): + ts-jest@29.4.12(@babel/core@7.29.7(supports-color@8.1.1))(@jest/transform@30.4.1(supports-color@8.1.1))(@jest/types@30.4.1)(babel-jest@29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(esbuild@0.28.2)(jest-util@30.4.1)(jest@29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(typescript@5.9.3): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 handlebars: 4.7.9 - jest: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3)) + jest: 29.7.0(@types/node@24.13.3)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.8.5 + type-fest: 4.41.0 + typescript: 5.9.3 + yargs-parser: 21.1.1 + optionalDependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@jest/transform': 30.4.1(supports-color@8.1.1) + '@jest/types': 30.4.1 + babel-jest: 29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + esbuild: 0.28.2 + jest-util: 30.4.1 + + ts-jest@29.4.12(@babel/core@7.29.7(supports-color@8.1.1))(@jest/transform@30.4.1(supports-color@8.1.1))(@jest/types@30.4.1)(babel-jest@29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(esbuild@0.28.2)(jest-util@30.4.1)(jest@29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)))(typescript@6.0.3): + dependencies: + bs-logger: 0.2.6 + fast-json-stable-stringify: 2.1.0 + handlebars: 4.7.9 + jest: 29.7.0(@types/node@25.9.5)(supports-color@8.1.1)(ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3)) json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 @@ -8591,44 +8854,44 @@ snapshots: '@babel/core': 7.29.7(supports-color@8.1.1) '@jest/transform': 30.4.1(supports-color@8.1.1) '@jest/types': 30.4.1 - babel-jest: 30.4.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) - esbuild: 0.28.1 + babel-jest: 29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + esbuild: 0.28.2 jest-util: 30.4.1 - ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3): + ts-node@10.9.2(@types/node@25.9.5)(typescript@6.0.3): dependencies: '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 + '@tsconfig/node10': 1.0.13 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 24.13.3 + '@types/node': 25.9.5 acorn: 8.18.0 acorn-walk: 8.3.5 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.4 make-error: 1.3.6 - typescript: 5.9.3 + typescript: 6.0.3 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 tslib@2.8.1: {} - tsx@4.23.5: + tsx@4.23.12: dependencies: - esbuild: 0.28.1 + esbuild: 0.28.2 optionalDependencies: fsevents: 2.3.3 - turbo@2.10.8: + turbo@2.10.5: optionalDependencies: - '@turbo/darwin-64': 2.10.8 - '@turbo/darwin-arm64': 2.10.8 - '@turbo/linux-64': 2.10.8 - '@turbo/linux-arm64': 2.10.8 - '@turbo/windows-64': 2.10.8 - '@turbo/windows-arm64': 2.10.8 + '@turbo/darwin-64': 2.10.5 + '@turbo/darwin-arm64': 2.10.5 + '@turbo/linux-64': 2.10.5 + '@turbo/linux-arm64': 2.10.5 + '@turbo/windows-64': 2.10.5 + '@turbo/windows-arm64': 2.10.5 type-check@0.4.0: dependencies: @@ -8675,23 +8938,12 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3): + typescript-eslint@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) - '@typescript-eslint/parser': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.65.0(supports-color@8.1.1)(typescript@5.9.3) - '@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3) - eslint: 9.39.5(supports-color@8.1.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - typescript-eslint@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3): - dependencies: - '@typescript-eslint/eslint-plugin': 8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) - '@typescript-eslint/parser': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) - '@typescript-eslint/typescript-estree': 8.65.0(supports-color@8.1.1)(typescript@6.0.3) - '@typescript-eslint/utils': 8.65.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/eslint-plugin': 8.67.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3))(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.67.0(supports-color@8.1.1)(typescript@6.0.3) + '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) eslint: 9.39.5(supports-color@8.1.1) typescript: 6.0.3 transitivePeerDependencies: @@ -8744,9 +8996,9 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.12.2 '@unrs/resolver-binding-win32-x64-msvc': 1.12.2 - update-browserslist-db@1.2.3(browserslist@4.28.7): + update-browserslist-db@1.3.1(browserslist@4.28.8): dependencies: - browserslist: 4.28.7 + browserslist: 4.28.8 escalade: 3.2.0 picocolors: 1.1.1 @@ -8899,7 +9151,7 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 4.1.0 - ws@8.21.1: {} + ws@8.21.3: {} xml-name-validator@4.0.0: {} @@ -8948,24 +9200,30 @@ snapshots: zod@4.4.3: {} time: - '@aws-sdk/client-eventbridge@3.1101.0': '2026-07-31T18:54:01.860Z' - '@aws-sdk/client-lambda@3.1101.0': '2026-07-31T18:55:13.820Z' - '@aws-sdk/client-s3@3.1101.0': '2026-07-31T18:51:01.862Z' - '@aws-sdk/client-ssm@3.1101.0': '2026-07-31T18:58:13.556Z' - '@aws-sdk/types@3.974.2': '2026-07-15T18:50:46.412Z' + '@aws-sdk/client-cloudwatch-logs@3.1113.0': '2026-08-18T19:01:05.767Z' + '@aws-sdk/client-dynamodb@3.1113.0': '2026-08-18T18:58:57.476Z' + '@aws-sdk/client-eventbridge@3.1111.0': '2026-08-14T18:58:40.229Z' + '@aws-sdk/client-eventbridge@3.1113.0': '2026-08-18T18:58:24.439Z' + '@aws-sdk/client-lambda@3.1111.0': '2026-08-14T18:59:55.213Z' + '@aws-sdk/client-s3@3.1111.0': '2026-08-14T18:55:29.162Z' + '@aws-sdk/client-s3@3.1113.0': '2026-08-18T18:56:30.230Z' + '@aws-sdk/client-sqs@3.1113.0': '2026-08-18T19:02:30.793Z' + '@aws-sdk/client-ssm@3.1111.0': '2026-08-14T19:03:01.669Z' + '@aws-sdk/lib-dynamodb@3.1113.0': '2026-08-18T18:56:22.295Z' + '@aws-sdk/types@3.974.4': '2026-08-14T18:53:31.355Z' '@eslint/js@9.39.5': '2026-07-10T20:16:17.272Z' '@stylistic/eslint-plugin-ts@4.4.1': '2025-06-04T05:15:11.157Z' '@stylistic/eslint-plugin@3.1.0': '2025-02-08T03:32:25.887Z' - '@tsconfig/node22@22.0.5': '2025-11-18T04:18:10.669Z' + '@tsconfig/node22@22.0.6': '2026-08-15T04:22:35.521Z' '@types/aws-lambda@8.10.162': '2026-06-06T12:54:37.547Z' '@types/jest@29.5.14': '2024-10-23T03:43:49.927Z' '@types/jsonwebtoken@9.0.10': '2025-06-16T07:36:00.187Z' '@types/node@24.13.3': '2026-07-08T06:48:03.261Z' '@types/node@25.9.5': '2026-07-08T06:47:58.834Z' '@types/qs@6.15.1': '2026-05-06T23:46:01.024Z' - '@types/semver@7.8.0': '2026-08-02T08:01:52.124Z' + '@types/semver@7.7.1': '2025-09-03T15:02:35.366Z' '@typescript-eslint/eslint-plugin@8.65.0': '2026-07-20T17:39:25.625Z' - '@typescript-eslint/parser@8.65.0': '2026-07-20T17:39:03.395Z' + '@typescript-eslint/parser@8.67.0': '2026-08-10T17:22:16.082Z' async-mutex@0.4.1: '2024-01-17T21:30:34.828Z' aws-sdk-client-mock-jest@4.1.0: '2024-10-15T12:49:36.193Z' aws-sdk-client-mock@4.1.0: '2024-10-15T12:49:34.458Z' @@ -8977,7 +9235,7 @@ time: eslint-import-resolver-typescript@4.4.5: '2026-06-01T04:17:50.360Z' eslint-plugin-html@8.1.4: '2026-01-23T14:05:26.428Z' eslint-plugin-import-x@4.17.1: '2026-06-28T07:00:54.891Z' - eslint-plugin-jest@29.16.0: '2026-07-24T05:07:19.397Z' + eslint-plugin-jest@29.16.1: '2026-08-12T05:52:24.973Z' eslint-plugin-json@4.0.1: '2024-08-07T22:51:29.877Z' eslint-plugin-jsx-a11y@6.10.2: '2024-10-26T04:45:18.067Z' eslint-plugin-no-relative-import-paths@1.6.1: '2025-01-07T15:01:05.204Z' @@ -8989,7 +9247,7 @@ time: eslint-plugin-sort-destructure-keys@2.0.0: '2024-04-24T05:18:05.644Z' eslint-plugin-unicorn@61.0.2: '2025-09-08T09:24:37.952Z' eslint@9.39.5: '2026-07-10T20:41:47.507Z' - globals@17.9.0: '2026-08-02T15:24:47.623Z' + globals@17.11.0: '2026-08-12T11:07:59.530Z' jest-environment-jsdom@29.7.0: '2023-09-12T06:43:48.464Z' jest-html-reporter@4.4.0: '2026-03-28T08:26:31.721Z' jest-mock-extended@3.0.7: '2024-05-02T09:32:24.366Z' @@ -8998,13 +9256,14 @@ time: jose@5.10.0: '2025-02-17T15:07:27.617Z' jsonwebtoken@9.0.3: '2025-12-04T10:27:57.257Z' lcov-result-merger@5.0.1: '2024-05-17T08:48:24.166Z' + pino@10.3.1: '2026-02-09T15:50:56.728Z' qs@6.15.3: '2026-06-24T20:03:49.752Z' semver@7.8.5: '2026-06-19T18:32:48.972Z' ts-jest@29.4.12: '2026-07-22T07:47:19.343Z' ts-node@10.9.2: '2023-12-08T12:04:46.154Z' - tsx@4.23.5: '2026-08-02T23:18:23.595Z' - turbo@2.10.8: '2026-07-31T14:23:18.916Z' - typescript-eslint@8.65.0: '2026-07-20T17:39:32.402Z' + tsx@4.23.12: '2026-08-10T03:41:31.093Z' + turbo@2.10.5: '2026-07-13T17:00:16.327Z' + typescript-eslint@8.67.0: '2026-08-10T17:22:44.231Z' typescript@5.9.3: '2025-09-30T21:19:38.784Z' typescript@6.0.3: '2026-04-16T23:38:27.905Z' winston@3.19.0: '2025-12-07T07:37:16.009Z' diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ffd11c4..38883b1 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,5 @@ packages: + - "packages/*" - "src/lambdas/apim-access-token-refresher" - "src/lambdas/apim-key-generator" - "src/utils" @@ -15,6 +16,13 @@ allowBuilds: blockExoticSubdeps: true catalogs: + aws: + "@aws-sdk/client-cloudwatch-logs": "^3.1113.0" + "@aws-sdk/client-dynamodb": "^3.1113.0" + "@aws-sdk/client-eventbridge": "^3.1113.0" + "@aws-sdk/client-s3": "^3.1113.0" + "@aws-sdk/client-sqs": "^3.1113.0" + "@aws-sdk/lib-dynamodb": "^3.1113.0" build: turbo: "^2.9.6" lint: @@ -41,6 +49,8 @@ catalogs: eslint-plugin-sort-destructure-keys: "^2.0.0" eslint-plugin-unicorn: "^61.0.2" typescript-eslint: "^8.46.1" + runtime: + pino: "^10.3.1" test: "@types/jest": "^29.5.0" "@types/mock-fs": "^4.13.4" @@ -64,6 +74,13 @@ catalogs: engineStrict: true minimumReleaseAge: 2880 +minimumReleaseAgeExclude: + - '@aws-sdk/client-cloudwatch-logs@3.1113.0' + - '@aws-sdk/client-dynamodb@3.1113.0' + - '@aws-sdk/client-eventbridge@3.1113.0' + - '@aws-sdk/client-s3@3.1113.0' + - '@aws-sdk/client-sqs@3.1113.0' + - '@aws-sdk/lib-dynamodb@3.1113.0' nodeOptions: "${NODE_OPTIONS:- } --experimental-vm-modules" overrides: diff --git a/scripts/config/vale/styles/config/vocabularies/words/accept.txt b/scripts/config/vale/styles/config/vocabularies/words/accept.txt index 0d569d6..99451a9 100644 --- a/scripts/config/vale/styles/config/vocabularies/words/accept.txt +++ b/scripts/config/vale/styles/config/vocabularies/words/accept.txt @@ -1,3 +1,4 @@ +[Aa]sync [Bb]undler Bitwarden bot @@ -19,6 +20,7 @@ GitHub Gitleaks Grype idempotence +[Ii]njectable Jira lockfile markdownlint @@ -26,16 +28,21 @@ npm OAuth Octokit onboarding +[Pp]ino Podman [Pp]npm Python rawContent relative_url [Rr]epo +[Rr]ethrown sed simplifiable +[Ss]ubpath Syft toolchain Trivy Trufflehog [Tt]erraform +[Vv]alidator +[Zz]od diff --git a/src/lambdas/apim-access-token-refresher/tsconfig.json b/src/lambdas/apim-access-token-refresher/tsconfig.json index de8ca2a..09d1b45 100644 --- a/src/lambdas/apim-access-token-refresher/tsconfig.json +++ b/src/lambdas/apim-access-token-refresher/tsconfig.json @@ -1,7 +1,10 @@ { "compilerOptions": { - "baseUrl": "./src/", - "isolatedModules": true + "isolatedModules": true, + "paths": { + "*": ["./src/*"] + }, + "types": ["jest", "node"] }, "exclude": [ "node_modules" diff --git a/src/lambdas/apim-key-generator/tsconfig.json b/src/lambdas/apim-key-generator/tsconfig.json index de8ca2a..09d1b45 100644 --- a/src/lambdas/apim-key-generator/tsconfig.json +++ b/src/lambdas/apim-key-generator/tsconfig.json @@ -1,7 +1,10 @@ { "compilerOptions": { - "baseUrl": "./src/", - "isolatedModules": true + "isolatedModules": true, + "paths": { + "*": ["./src/*"] + }, + "types": ["jest", "node"] }, "exclude": [ "node_modules" diff --git a/src/utils/tsconfig.json b/src/utils/tsconfig.json index de8ca2a..09d1b45 100644 --- a/src/utils/tsconfig.json +++ b/src/utils/tsconfig.json @@ -1,7 +1,10 @@ { "compilerOptions": { - "baseUrl": "./src/", - "isolatedModules": true + "isolatedModules": true, + "paths": { + "*": ["./src/*"] + }, + "types": ["jest", "node"] }, "exclude": [ "node_modules" diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..beb1c0d --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@tsconfig/node22/tsconfig.json", + "compilerOptions": { + "declaration": true, + "resolveJsonModule": true + } +} diff --git a/turbo.json b/turbo.json index 16d8aa3..8ffa38c 100644 --- a/turbo.json +++ b/turbo.json @@ -1,6 +1,19 @@ { "$schema": "https://turborepo.dev/schema.json", "tasks": { + "build": { + "dependsOn": [ + "^build" + ], + "inputs": [ + "src/**/*.ts", + "tsconfig.json", + "tsconfig.build.json" + ], + "outputs": [ + "dist/**" + ] + }, "lint": { "dependsOn": [ "^lint"