From 26240f49ff962e820a2857f78b74632c0c126cf7 Mon Sep 17 00:00:00 2001 From: Joakim Carlstein Date: Thu, 24 Apr 2025 15:06:32 +0200 Subject: [PATCH] fix(mysql): make sure migrations are run in order when run concurrently Now we either lock all or none of the migrations to run, to make sure they are not out of order when multiple instances of Emigrate run concurrently. --- .changeset/bright-poems-approve.md | 5 + .changeset/yellow-walls-tease.md | 5 + .github/workflows/ci.yaml | 25 +- .github/workflows/release.yaml | 2 +- package.json | 3 +- packages/cli/src/commands/remove.test.ts | 15 +- packages/cli/src/commands/up.test.ts | 57 +-- packages/cli/src/test-utils.ts | 22 + packages/mysql/package.json | 8 +- packages/mysql/src/index.test.ts | 92 ++++ packages/mysql/src/index.ts | 116 ++++- packages/mysql/src/tests/database.ts | 45 ++ pnpm-lock.yaml | 625 ++++++++++++++++++++++- 13 files changed, 922 insertions(+), 98 deletions(-) create mode 100644 .changeset/bright-poems-approve.md create mode 100644 .changeset/yellow-walls-tease.md create mode 100644 packages/mysql/src/index.test.ts create mode 100644 packages/mysql/src/tests/database.ts diff --git a/.changeset/bright-poems-approve.md b/.changeset/bright-poems-approve.md new file mode 100644 index 0000000..4045f29 --- /dev/null +++ b/.changeset/bright-poems-approve.md @@ -0,0 +1,5 @@ +--- +'@emigrate/mysql': patch +--- + +Make sure we can initialize multiple running instances of Emigrate using @emigrate/mysql concurrently without issues with creating the history table (for instance in a Kubernetes environment and/or with a Percona cluster). diff --git a/.changeset/yellow-walls-tease.md b/.changeset/yellow-walls-tease.md new file mode 100644 index 0000000..2a0a22f --- /dev/null +++ b/.changeset/yellow-walls-tease.md @@ -0,0 +1,5 @@ +--- +'@emigrate/mysql': patch +--- + +Either lock all or none of the migrations to run to make sure they run in order when multiple instances of Emigrate runs concurrently (for instance in a Kubernetes environment) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 01a8453..b81d6b1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,6 +15,18 @@ jobs: TURBO_TEAM: ${{ secrets.TURBO_TEAM }} DO_NOT_TRACK: 1 + services: + mysql: + image: mysql:8.0 + env: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: emigrate + MYSQL_USER: emigrate + MYSQL_PASSWORD: emigrate + ports: + - 3306:3306 + options: --health-cmd="mysqladmin ping -h localhost" --health-interval=10s --health-timeout=5s --health-retries=5 + steps: - name: Check out code uses: actions/checkout@v4 @@ -26,11 +38,22 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v4 with: - node-version: 20.9.0 + node-version: 22.15.0 cache: 'pnpm' - name: Install dependencies run: pnpm install + - name: Wait for MySQL to be ready + run: | + for i in {1..30}; do + nc -z localhost 3306 && echo "MySQL is up!" && break + echo "Waiting for MySQL..." + sleep 2 + done + - name: Checks + env: + MYSQL_HOST: localhost + MYSQL_PORT: 3306 run: pnpm checks diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 702a702..8b42c24 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -30,7 +30,7 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v4 with: - node-version: 20.9.0 + node-version: 22.15.0 cache: 'pnpm' - name: Install Dependencies diff --git a/package.json b/package.json index 48cdaac..a2207a0 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "bugs": "https://github.com/aboviq/emigrate/issues", "license": "MIT", "volta": { - "node": "20.9.0", + "node": "22.15.0", "pnpm": "9.4.0" }, "packageManager": "pnpm@9.4.0", @@ -80,6 +80,7 @@ "lint-staged": "15.2.0", "npm-run-all": "4.1.5", "prettier": "3.1.1", + "testcontainers": "10.24.2", "tsx": "4.15.7", "turbo": "2.0.5", "typescript": "5.5.2", diff --git a/packages/cli/src/commands/remove.test.ts b/packages/cli/src/commands/remove.test.ts index a283551..f37769b 100644 --- a/packages/cli/src/commands/remove.test.ts +++ b/packages/cli/src/commands/remove.test.ts @@ -11,6 +11,7 @@ import { StorageInitError, } from '../errors.js'; import { + assertErrorEqualEnough, getErrorCause, getMockedReporter, getMockedStorage, @@ -199,6 +200,11 @@ function assertPreconditionsFailed(reporter: Mocked>, assert.strictEqual(reporter.onMigrationSkip.mock.calls.length, 0, 'Total pending and skipped'); assert.strictEqual(reporter.onFinished.mock.calls.length, 1, 'Finished called once'); const [entries, error] = reporter.onFinished.mock.calls[0]?.arguments ?? []; + // hackety hack: + if (finishedError) { + finishedError.stack = error?.stack; + } + assert.deepStrictEqual(error, finishedError, 'Finished error'); const cause = getErrorCause(error); const expectedCause = finishedError?.cause; @@ -288,14 +294,7 @@ function assertPreconditionsFulfilled( assert.strictEqual(reporter.onMigrationSkip.mock.calls.length, 0, 'Total pending and skipped'); assert.strictEqual(reporter.onFinished.mock.calls.length, 1, 'Finished called once'); const [entries, error] = reporter.onFinished.mock.calls[0]?.arguments ?? []; - assert.deepStrictEqual(error, finishedError, 'Finished error'); - const cause = getErrorCause(error); - const expectedCause = finishedError?.cause; - assert.deepStrictEqual( - cause, - expectedCause ? deserializeError(expectedCause) : expectedCause, - 'Finished error cause', - ); + assertErrorEqualEnough(error, finishedError, 'Finished error'); assert.strictEqual(entries?.length, expected.length, 'Finished entries length'); assert.deepStrictEqual( entries.map((entry) => `${entry.name} (${entry.status})`), diff --git a/packages/cli/src/commands/up.test.ts b/packages/cli/src/commands/up.test.ts index 869af10..bc90241 100644 --- a/packages/cli/src/commands/up.test.ts +++ b/packages/cli/src/commands/up.test.ts @@ -1,13 +1,6 @@ import { describe, it, mock } from 'node:test'; import assert from 'node:assert'; -import { - type EmigrateReporter, - type Storage, - type Plugin, - type SerializedError, - type MigrationMetadataFinished, -} from '@emigrate/types'; -import { deserializeError } from 'serialize-error'; +import { type EmigrateReporter, type Storage, type Plugin, type MigrationMetadataFinished } from '@emigrate/types'; import { version } from '../get-package-info.js'; import { BadOptionError, @@ -16,7 +9,6 @@ import { MigrationHistoryError, MigrationRunError, StorageInitError, - toSerializedError, } from '../errors.js'; import { type Mocked, @@ -24,7 +16,7 @@ import { toMigrations, getMockedReporter, getMockedStorage, - getErrorCause, + assertErrorEqualEnough, } from '../test-utils.js'; import upCommand from './up.js'; @@ -930,15 +922,13 @@ function assertPreconditionsFulfilled( for (const [index, entry] of failedEntries.entries()) { if (entry.status === 'failed') { const error = reporter.onMigrationError.mock.calls[index]?.arguments[1]; - assert.deepStrictEqual(error, entry.error, 'Error'); - const cause = entry.error?.cause; - assert.deepStrictEqual(error?.cause, cause ? deserializeError(cause) : cause, 'Error cause'); + assertErrorEqualEnough(error, entry.error, 'Error'); if (entry.started) { const [finishedMigration, error] = storage.onError.mock.calls[index]?.arguments ?? []; assert.strictEqual(finishedMigration?.name, entry.name); assert.strictEqual(finishedMigration?.status, entry.status); - assertErrorEqualEnough(error, entry.error); + assertErrorEqualEnough(error, entry.error, `Entry error (${entry.name})`); } } } @@ -946,15 +936,7 @@ function assertPreconditionsFulfilled( assert.strictEqual(reporter.onMigrationSkip.mock.calls.length, pending + skipped, 'Total pending and skipped'); assert.strictEqual(reporter.onFinished.mock.calls.length, 1, 'Finished called once'); const [entries, error] = reporter.onFinished.mock.calls[0]?.arguments ?? []; - assertErrorEqualEnough(error, finishedError); - - const cause = getErrorCause(error); - const expectedCause = finishedError?.cause; - assert.deepStrictEqual( - cause, - expectedCause ? deserializeError(expectedCause) : expectedCause, - 'Finished error cause', - ); + assertErrorEqualEnough(error, finishedError, 'Finished error'); assert.strictEqual(entries?.length, expected.length, 'Finished entries length'); assert.deepStrictEqual( entries.map((entry) => `${entry.name} (${entry.status})`), @@ -995,33 +977,6 @@ function assertPreconditionsFailed( assert.strictEqual(reporter.onMigrationSkip.mock.calls.length, 0, 'Total pending and skipped'); assert.strictEqual(reporter.onFinished.mock.calls.length, 1, 'Finished called once'); const [entries, error] = reporter.onFinished.mock.calls[0]?.arguments ?? []; - assert.deepStrictEqual(error, finishedError, 'Finished error'); - const cause = getErrorCause(error); - const expectedCause = finishedError?.cause; - assert.deepStrictEqual( - cause, - expectedCause ? deserializeError(expectedCause) : expectedCause, - 'Finished error cause', - ); + assertErrorEqualEnough(error, finishedError, 'Finished error'); assert.strictEqual(entries?.length, 0, 'Finished entries length'); } - -function assertErrorEqualEnough(actual?: Error | SerializedError, expected?: Error) { - if (expected === undefined) { - assert.strictEqual(actual, undefined); - return; - } - - const { - cause: actualCause, - stack: actualStack, - ...actualError - } = actual instanceof Error ? toSerializedError(actual) : actual ?? {}; - const { cause: expectedCause, stack: expectedStack, ...expectedError } = toSerializedError(expected); - // @ts-expect-error Ignore - const { stack: actualCauseStack, ...actualCauseRest } = actualCause ?? {}; - // @ts-expect-error Ignore - const { stack: expectedCauseStack, ...expectedCauseRest } = expectedCause ?? {}; - assert.deepStrictEqual(actualError, expectedError); - assert.deepStrictEqual(actualCauseRest, expectedCauseRest); -} diff --git a/packages/cli/src/test-utils.ts b/packages/cli/src/test-utils.ts index 38e2afc..0ede3fe 100644 --- a/packages/cli/src/test-utils.ts +++ b/packages/cli/src/test-utils.ts @@ -1,5 +1,6 @@ import { mock, type Mock } from 'node:test'; import path from 'node:path'; +import assert from 'node:assert'; import { type SerializedError, type EmigrateReporter, @@ -9,6 +10,7 @@ import { type NonFailedMigrationHistoryEntry, type Storage, } from '@emigrate/types'; +import { toSerializedError } from './errors.js'; export type Mocked = { // @ts-expect-error - This is a mock @@ -110,3 +112,23 @@ export function toEntries( ): MigrationHistoryEntry[] { return names.map((name) => (typeof name === 'string' ? toEntry(name, status) : name)); } + +export function assertErrorEqualEnough(actual?: Error | SerializedError, expected?: Error, message?: string): void { + if (expected === undefined) { + assert.strictEqual(actual, undefined); + return; + } + + const { + cause: actualCause, + stack: actualStack, + ...actualError + } = actual instanceof Error ? toSerializedError(actual) : actual ?? {}; + const { cause: expectedCause, stack: expectedStack, ...expectedError } = toSerializedError(expected); + // @ts-expect-error Ignore + const { stack: actualCauseStack, ...actualCauseRest } = actualCause ?? {}; + // @ts-expect-error Ignore + const { stack: expectedCauseStack, ...expectedCauseRest } = expectedCause ?? {}; + assert.deepStrictEqual(actualError, expectedError, message); + assert.deepStrictEqual(actualCauseRest, expectedCauseRest, message ? `${message} (cause)` : undefined); +} diff --git a/packages/mysql/package.json b/packages/mysql/package.json index 66fa554..4e75919 100644 --- a/packages/mysql/package.json +++ b/packages/mysql/package.json @@ -17,12 +17,16 @@ }, "files": [ "dist", - "!dist/*.tsbuildinfo" + "!dist/*.tsbuildinfo", + "!dist/**/*.test.js", + "!dist/tests/*" ], "scripts": { "build": "tsc --pretty", "build:watch": "tsc --pretty --watch", - "lint": "xo --cwd=../.. $(pwd)" + "lint": "xo --cwd=../.. $(pwd)", + "test-disabled": "glob -c \"node --import tsx --test-reporter spec --test\" \"./src/**/*.test.ts\"", + "test:watch": "glob -c \"node --watch --import tsx --test-reporter spec --test\" \"./src/**/*.test.ts\"" }, "keywords": [ "emigrate", diff --git a/packages/mysql/src/index.test.ts b/packages/mysql/src/index.test.ts new file mode 100644 index 0000000..240e3ff --- /dev/null +++ b/packages/mysql/src/index.test.ts @@ -0,0 +1,92 @@ +import assert from 'node:assert'; +import path from 'node:path'; +import { before, after, describe, it } from 'node:test'; +import type { MigrationMetadata } from '@emigrate/types'; +import { startDatabase, stopDatabase } from './tests/database.js'; +import { createMysqlStorage } from './index.js'; + +let db: { port: number; host: string }; + +describe('emigrate-mysql', async () => { + before( + async () => { + db = await startDatabase(); + }, + { timeout: 60_000 }, + ); + + after( + async () => { + await stopDatabase(); + }, + { timeout: 10_000 }, + ); + + describe('migration locks', async () => { + it('either locks none or all of the given migrations', async () => { + const { initializeStorage } = createMysqlStorage({ + table: 'migrations', + connection: { + host: db.host, + user: 'emigrate', + password: 'emigrate', + database: 'emigrate', + port: db.port, + }, + }); + + const [storage1, storage2] = await Promise.all([initializeStorage(), initializeStorage()]); + + const migrations = toMigrations('/emigrate', 'migrations', [ + '2023-10-01-01-test.js', + '2023-10-01-02-test.js', + '2023-10-01-03-test.js', + '2023-10-01-04-test.js', + '2023-10-01-05-test.js', + '2023-10-01-06-test.js', + '2023-10-01-07-test.js', + '2023-10-01-08-test.js', + '2023-10-01-09-test.js', + '2023-10-01-10-test.js', + '2023-10-01-11-test.js', + '2023-10-01-12-test.js', + '2023-10-01-13-test.js', + '2023-10-01-14-test.js', + '2023-10-01-15-test.js', + '2023-10-01-16-test.js', + '2023-10-01-17-test.js', + '2023-10-01-18-test.js', + '2023-10-01-19-test.js', + '2023-10-01-20-test.js', + ]); + + const [locked1, locked2] = await Promise.all([storage1.lock(migrations), storage2.lock(migrations)]); + + assert.strictEqual( + locked1.length === 0 || locked2.length === 0, + true, + 'One of the processes should have no locks', + ); + assert.strictEqual( + locked1.length === 20 || locked2.length === 20, + true, + 'One of the processes should have all locks', + ); + }); + }); +}); + +function toMigration(cwd: string, directory: string, name: string): MigrationMetadata { + return { + name, + filePath: `${cwd}/${directory}/${name}`, + relativeFilePath: `${directory}/${name}`, + extension: path.extname(name), + directory, + cwd, + }; +} + +function toMigrations(cwd: string, directory: string, names: string[]): MigrationMetadata[] { + return names.map((name) => toMigration(cwd, directory, name)); +} diff --git a/packages/mysql/src/index.ts b/packages/mysql/src/index.ts index 2d4b254..8dc1b87 100644 --- a/packages/mysql/src/index.ts +++ b/packages/mysql/src/index.ts @@ -1,5 +1,6 @@ import process from 'node:process'; import fs from 'node:fs/promises'; +import { setTimeout } from 'node:timers/promises'; import { createConnection, createPool, @@ -54,6 +55,7 @@ const getConnection = async (options: ConnectionOptions | string) => { // best to leave this at 0 (disabled) uri.searchParams.set('connectTimeout', '0'); uri.searchParams.set('multipleStatements', 'true'); + uri.searchParams.set('flags', '-FOUND_ROWS'); connection = await createConnection(uri.toString()); } else { @@ -64,6 +66,7 @@ const getConnection = async (options: ConnectionOptions | string) => { // best to leave this at 0 (disabled) connectTimeout: 0, multipleStatements: true, + flags: ['-FOUND_ROWS'], }); } @@ -84,6 +87,7 @@ const getPool = (connection: PoolOptions | string) => { // it throws an error you can't catch and crashes node // best to leave this at 0 (disabled) uri.searchParams.set('connectTimeout', '0'); + uri.searchParams.set('flags', '-FOUND_ROWS'); return createPool(uri.toString()); } @@ -94,6 +98,7 @@ const getPool = (connection: PoolOptions | string) => { // it throws an error you can't catch and crashes node // best to leave this at 0 (disabled) connectTimeout: 0, + flags: ['-FOUND_ROWS'], }); }; @@ -104,8 +109,8 @@ type HistoryEntry = { error?: SerializedError; }; -const lockMigration = async (pool: Pool, table: string, migration: MigrationMetadata) => { - const [result] = await pool.execute({ +const lockMigration = async (connection: Connection, table: string, migration: MigrationMetadata) => { + const [result] = await connection.execute({ sql: ` INSERT INTO ${escapeId(table)} (name, status, date) VALUES (?, ?, NOW()) @@ -228,8 +233,10 @@ const initializeDatabase = async (config: ConnectionOptions | string) => { } }; -const initializeTable = async (pool: Pool, table: string) => { - const [result] = await pool.execute({ +const lockWaitTimeout = 10; // seconds + +const isHistoryTableExisting = async (connection: Connection, table: string) => { + const [result] = await connection.execute({ sql: ` SELECT 1 as table_exists @@ -242,24 +249,70 @@ const initializeTable = async (pool: Pool, table: string) => { values: [table], }); - if (result[0]?.['table_exists']) { + return result[0]?.['table_exists'] === 1; +}; + +const initializeTable = async (config: ConnectionOptions | string, table: string) => { + const connection = await getConnection(config); + + if (await isHistoryTableExisting(connection, table)) { + await connection.end(); return; } - // This table definition is compatible with the one used by the immigration-mysql package - await pool.execute(` - CREATE TABLE ${escapeId(table)} ( - name varchar(255) not null primary key, - status varchar(32), - date datetime not null - ) Engine=InnoDB; - `); + const lockName = `emigrate_init_table_lock_${table}`; + + const [lockResult] = await connection.query(`SELECT GET_LOCK(?, ?) AS got_lock`, [ + lockName, + lockWaitTimeout, + ]); + const didGetLock = lockResult[0]?.['got_lock'] === 1; + + if (didGetLock) { + try { + // This table definition is compatible with the one used by the immigration-mysql package + await connection.execute(` + CREATE TABLE IF NOT EXISTS ${escapeId(table)} ( + name varchar(255) not null primary key, + status varchar(32), + date datetime not null + ) Engine=InnoDB; + `); + } finally { + await connection.query(`SELECT RELEASE_LOCK(?)`, [lockName]); + await connection.end(); + } + + return; + } + + // Didn't get the lock, wait to see if the table was created by another process + const maxWait = lockWaitTimeout * 1000; // milliseconds + const checkInterval = 250; // milliseconds + const start = Date.now(); + + try { + while (Date.now() - start < maxWait) { + // eslint-disable-next-line no-await-in-loop + if (await isHistoryTableExisting(connection, table)) { + return; + } + + // eslint-disable-next-line no-await-in-loop + await setTimeout(checkInterval); + } + + throw new Error(`Timeout waiting for table ${table} to be created by other process`); + } finally { + await connection.end(); + } }; export const createMysqlStorage = ({ table = defaultTable, connection }: MysqlStorageOptions): EmigrateStorage => { return { async initializeStorage() { await initializeDatabase(connection); + await initializeTable(connection, table); const pool = getPool(connection); @@ -271,24 +324,35 @@ export const createMysqlStorage = ({ table = defaultTable, connection }: MysqlSt }); } - try { - await initializeTable(pool, table); - } catch (error) { - await pool.end(); - throw error; - } - const storage: Storage = { async lock(migrations) { - const lockedMigrations: MigrationMetadata[] = []; + const connection = await pool.getConnection(); - for await (const migration of migrations) { - if (await lockMigration(pool, table, migration)) { - lockedMigrations.push(migration); + try { + await connection.beginTransaction(); + const lockedMigrations: MigrationMetadata[] = []; + + for await (const migration of migrations) { + if (await lockMigration(connection, table, migration)) { + lockedMigrations.push(migration); + } } - } - return lockedMigrations; + if (lockedMigrations.length === migrations.length) { + await connection.commit(); + + return lockedMigrations; + } + + await connection.rollback(); + + return []; + } catch (error) { + await connection.rollback(); + throw error; + } finally { + connection.release(); + } }, async unlock(migrations) { for await (const migration of migrations) { diff --git a/packages/mysql/src/tests/database.ts b/packages/mysql/src/tests/database.ts new file mode 100644 index 0000000..2270969 --- /dev/null +++ b/packages/mysql/src/tests/database.ts @@ -0,0 +1,45 @@ +/* eslint @typescript-eslint/naming-convention:0, import/no-extraneous-dependencies: 0 */ +import process from 'node:process'; +import { GenericContainer, type StartedTestContainer } from 'testcontainers'; + +let container: StartedTestContainer | undefined; + +export const startDatabase = async (): Promise<{ port: number; host: string }> => { + if (process.env['CI']) { + return { + port: process.env['MYSQL_PORT'] ? Number.parseInt(process.env['MYSQL_PORT'], 10) : 3306, + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + host: process.env['MYSQL_HOST'] || 'localhost', + }; + } + + if (!container) { + console.log('Starting MySQL container...'); + const containerSetup = new GenericContainer('mysql:8.2') + .withEnvironment({ + MYSQL_ROOT_PASSWORD: 'admin', + MYSQL_USER: 'emigrate', + MYSQL_PASSWORD: 'emigrate', + MYSQL_DATABASE: 'emigrate', + }) + .withTmpFs({ '/var/lib/mysql': 'rw' }) + .withCommand(['--sql-mode=NO_ENGINE_SUBSTITUTION', '--default-authentication-plugin=mysql_native_password']) + .withExposedPorts(3306) + .withReuse(); + + container = await containerSetup.start(); + + console.log('MySQL container started'); + } + + return { port: container.getMappedPort(3306), host: container.getHost() }; +}; + +export const stopDatabase = async (): Promise => { + if (container) { + console.log('Stopping MySQL container...'); + await container.stop(); + console.log('MySQL container stopped'); + container = undefined; + } +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a1844e2..d818d13 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ importers: prettier: specifier: 3.1.1 version: 3.1.1 + testcontainers: + specifier: 10.24.2 + version: 10.24.2 tsx: specifier: 4.15.7 version: 4.15.7 @@ -409,6 +412,9 @@ packages: resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==} engines: {node: '>=6.9.0'} + '@balena/dockerignore@1.0.2': + resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==} + '@changesets/apply-release-plan@7.0.0': resolution: {integrity: sha512-vfi69JR416qC9hWmFGSxj7N6wA5J222XNBmezSVATPWDVPIF7gkd4d8CpbEbXmRWbVrkoli3oerGS6dcL/BGsQ==} @@ -855,6 +861,19 @@ packages: '@expressive-code/plugin-text-markers@0.29.4': resolution: {integrity: sha512-U8rouNRrLzAo11Ihoi4iqEH7FD+VEUb6Pe7xJxlFJ7HRhgaFIcuHyYyn6jA1WmGP5k9BFLhYBk53+oKvlmEkKw==} + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + + '@grpc/grpc-js@1.13.3': + resolution: {integrity: sha512-FTXHdOoPbZrBjlVLHuKbDZnsTxXv2BlHF57xw6LuThXacXvtkahEPED0CKMk6obZDf65Hv4k3z62eyPNpvinIg==} + engines: {node: '>=12.10.0'} + + '@grpc/proto-loader@0.7.15': + resolution: {integrity: sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==} + engines: {node: '>=6'} + hasBin: true + '@humanwhocodes/config-array@0.11.13': resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} engines: {node: '>=10.10.0'} @@ -911,6 +930,9 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@js-sdsl/ordered-map@4.4.2': + resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} + '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -968,6 +990,36 @@ packages: resolution: {integrity: sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@rollup/rollup-android-arm-eabi@4.9.0': resolution: {integrity: sha512-+1ge/xmaJpm1KVBuIH38Z94zj9fBD+hp+/5WLaHgyY8XLq1ibxk/zj6dTXaqM2cAbYKq8jYlhHd6k05If1W5xA==} cpu: [arm] @@ -1057,6 +1109,12 @@ packages: '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + '@types/docker-modem@3.0.6': + resolution: {integrity: sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==} + + '@types/dockerode@3.3.38': + resolution: {integrity: sha512-nnrcfUe2iR+RyOuz0B4bZgQwD9djQa9ADEjp7OAgBs10pYT0KSCtplJjcmBDJz0qaReX5T7GbE5i4VplvzUHvA==} + '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} @@ -1105,6 +1163,9 @@ packages: '@types/node@17.0.45': resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} + '@types/node@18.19.86': + resolution: {integrity: sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ==} + '@types/node@20.10.4': resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==} @@ -1126,6 +1187,15 @@ packages: '@types/semver@7.5.5': resolution: {integrity: sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==} + '@types/ssh2-streams@0.1.12': + resolution: {integrity: sha512-Sy8tpEmCce4Tq0oSOYdfqaBpA3hDM8SoxoFh5vzFsu2oL+znzGz8oVWW7xb4K920yYMUY+PIG31qZnFMfPWNCg==} + + '@types/ssh2@0.5.52': + resolution: {integrity: sha512-lbLLlXxdCZOSJMCInKH2+9V/77ET2J6NPQHpFI0kda61Dd1KglJs+fPQBchizmzYSOJBgdTajhPqBO1xxLywvg==} + + '@types/ssh2@1.15.5': + resolution: {integrity: sha512-N1ASjp/nXH3ovBHddRJpli4ozpk6UdDYIX4RJWFa9L1YKnzdhTlVmiGHm4DZnj/jLbqZpes4aeR30EFGQtvhQQ==} + '@types/unist@2.0.10': resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} @@ -1289,6 +1359,7 @@ packages: acorn-import-assertions@1.9.0: resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} + deprecated: package has been renamed to acorn-import-attributes peerDependencies: acorn: ^8 @@ -1367,6 +1438,14 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + archiver-utils@5.0.2: + resolution: {integrity: sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==} + engines: {node: '>= 14'} + + archiver@7.0.1: + resolution: {integrity: sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==} + engines: {node: '>= 14'} + arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -1416,6 +1495,9 @@ packages: resolution: {integrity: sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==} engines: {node: '>=12'} + asn1@0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + astring@1.8.6: resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==} hasBin: true @@ -1430,6 +1512,12 @@ packages: engines: {node: '>=18.14.1', npm: '>=6.14.0'} hasBin: true + async-lock@1.4.1: + resolution: {integrity: sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + atomic-sleep@1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} @@ -1454,6 +1542,36 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + bare-events@2.5.4: + resolution: {integrity: sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==} + + bare-fs@4.1.2: + resolution: {integrity: sha512-8wSeOia5B7LwD4+h465y73KOdj5QHsbbuoUfPBi+pXgFJIPuG7SsiOdJuijWMyfid49eD+WivpfY7KT8gbAzBA==} + engines: {bare: '>=1.16.0'} + peerDependencies: + bare-buffer: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + + bare-os@3.6.1: + resolution: {integrity: sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==} + engines: {bare: '>=1.14.0'} + + bare-path@3.0.0: + resolution: {integrity: sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==} + + bare-stream@2.6.5: + resolution: {integrity: sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==} + peerDependencies: + bare-buffer: '*' + bare-events: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + bare-events: + optional: true + base-64@1.0.0: resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} @@ -1466,6 +1584,9 @@ packages: bcp-47@2.1.0: resolution: {integrity: sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==} + bcrypt-pbkdf@1.0.2: + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} @@ -1518,6 +1639,10 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + buffer-crc32@1.0.0: + resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==} + engines: {node: '>=8.0.0'} + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -1527,6 +1652,10 @@ packages: buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + buildcheck@0.0.6: + resolution: {integrity: sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==} + engines: {node: '>=10.0.0'} + builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} @@ -1544,6 +1673,10 @@ packages: resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} engines: {node: '>=12'} + byline@5.0.0: + resolution: {integrity: sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==} + engines: {node: '>=0.10.0'} + call-bind@1.0.5: resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} @@ -1706,6 +1839,10 @@ packages: compare-func@2.0.0: resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + compress-commons@6.0.2: + resolution: {integrity: sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==} + engines: {node: '>= 14'} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -1732,6 +1869,9 @@ packages: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cosmiconfig-typescript-loader@5.0.0: resolution: {integrity: sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==} engines: {node: '>=v16'} @@ -1758,6 +1898,19 @@ packages: typescript: optional: true + cpu-features@0.0.10: + resolution: {integrity: sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==} + engines: {node: '>=10.0.0'} + + crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + + crc32-stream@6.0.0: + resolution: {integrity: sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==} + engines: {node: '>= 14'} + cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} @@ -1819,6 +1972,15 @@ packages: supports-color: optional: true + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decamelize-keys@1.1.1: resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} engines: {node: '>=0.10.0'} @@ -1912,6 +2074,18 @@ packages: dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + docker-compose@0.24.8: + resolution: {integrity: sha512-plizRs/Vf15H+GCVxq2EUvyPK7ei9b/cVesHvjnX4xaXjM9spHe2Ytq0BitndFgvTJ3E3NljPNUEl7BAN43iZw==} + engines: {node: '>= 6.0.0'} + + docker-modem@5.0.6: + resolution: {integrity: sha512-ens7BiayssQz/uAxGzH8zGXCtiV24rRWXdjNha5V4zSOcxmAZsfGVm/PPFbwQdqEkDnhG+SyR9E3zSHUbOKXBQ==} + engines: {node: '>= 8.0'} + + dockerode@4.0.6: + resolution: {integrity: sha512-FbVf3Z8fY/kALB9s+P9epCpWhfi/r0N2DgYYcYpsAUlaTxPjdsitsFobnltb+lyCgAIvf9C+4PSWlTnHlJMf1w==} + engines: {node: '>= 8.0'} + doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -2407,6 +2581,10 @@ packages: get-intrinsic@1.2.2: resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} + get-port@7.1.0: + resolution: {integrity: sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==} + engines: {node: '>=16'} + get-set-props@0.1.0: resolution: {integrity: sha512-7oKuKzAGKj0ag+eWZwcGw2fjiZ78tXnXQoBgY0aU7ZOxTu4bB7hSuQSDgtKy978EDH062P5FmD2EWiDpQS9K9Q==} engines: {node: '>=0.10.0'} @@ -2933,6 +3111,9 @@ packages: resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} engines: {node: '>=16'} + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -3035,6 +3216,10 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} + lazystream@1.0.1: + resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} + engines: {node: '>= 0.6.3'} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -3413,6 +3598,10 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + minimatch@9.0.3: resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} engines: {node: '>=16 || 14 >=14.17'} @@ -3435,12 +3624,20 @@ packages: mkdirp-classic@0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + muggle-string@0.4.1: resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} @@ -3455,6 +3652,9 @@ packages: resolution: {integrity: sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==} engines: {node: '>=12.0.0'} + nan@2.22.2: + resolution: {integrity: sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==} + nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -3870,6 +4070,9 @@ packages: probe-image-size@7.2.3: resolution: {integrity: sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w==} + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + process-warning@2.3.2: resolution: {integrity: sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA==} @@ -3881,6 +4084,13 @@ packages: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} + proper-lockfile@4.1.2: + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + + properties-reader@2.3.0: + resolution: {integrity: sha512-z597WicA7nDZxK12kZqHr2TcvwNU1GCfA5UwfDY/HDp3hXPoPlb5rlEx9bwGTiJnc0OqbBTkU975jDToth8Gxw==} + engines: {node: '>=14'} + property-information@6.4.0: resolution: {integrity: sha512-9t5qARVofg2xQqKtytzt+lZ4d1Qvj8t5B8fEwXK6qOfgRLgH/b13QlgEyDh033NOS31nXeFbYv7CLUDG1CeifQ==} @@ -3888,6 +4098,10 @@ packages: resolution: {integrity: sha512-2yma2tog9VaRZY2mn3Wq51uiSW4NcPYT1cQdBagwyrznrilKSZwIZ0UG3ZPL/mx+axEns0hE35T5ufOYZXEnBQ==} engines: {node: '>=4'} + protobufjs@7.5.0: + resolution: {integrity: sha512-Z2E/kOY1QjoMlCytmexzYfDm/w5fKAiRwpSzGtdnXW1zC88Z2yXazHHrOtwCzn+7wSxyE8PYM4rvVcMphF9sOA==} + engines: {node: '>=12.0.0'} + pseudomap@1.0.2: resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} @@ -3937,6 +4151,9 @@ packages: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -3945,6 +4162,9 @@ packages: resolution: {integrity: sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + readdir-glob@1.1.3: + resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -4062,6 +4282,10 @@ packages: retext@8.1.0: resolution: {integrity: sha512-N9/Kq7YTn6ZpzfiGW45WfEGJqFf1IM1q8OsRa1CGzIebCJBNCANDRmOrholiDRGKo/We7ofKR4SEvcGAWEMD3Q==} + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -4090,6 +4314,9 @@ packages: resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} engines: {node: '>=0.4'} + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -4273,6 +4500,9 @@ packages: spdx-license-ids@3.0.16: resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} + split-ca@1.0.1: + resolution: {integrity: sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==} + split2@3.2.2: resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} @@ -4287,6 +4517,13 @@ packages: resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} engines: {node: '>= 0.6'} + ssh-remote-port-forward@1.0.4: + resolution: {integrity: sha512-x0LV1eVDwjf1gmG7TTnfqIzf+3VPRz7vrNIjX6oYLbeCrf/PeVY6hkT68Mg+q02qXxQhrLjB0jfgvhevoCRmLQ==} + + ssh2@1.16.0: + resolution: {integrity: sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg==} + engines: {node: '>=10.16.0'} + stdin-discarder@0.1.0: resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -4300,6 +4537,9 @@ packages: streamx@2.15.6: resolution: {integrity: sha512-q+vQL4AAz+FdfT137VF69Cc/APqUbxy+MDOImRrMvchJpigHj9GksgDU2LYbO9rx7RX6osWgxJB2WxhYv4SZAw==} + streamx@2.22.0: + resolution: {integrity: sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==} + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -4338,6 +4578,9 @@ packages: string.prototype.trimstart@1.0.7: resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -4431,9 +4674,15 @@ packages: tar-fs@2.1.1: resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + tar-fs@2.1.2: + resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==} + tar-fs@3.0.4: resolution: {integrity: sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==} + tar-fs@3.0.8: + resolution: {integrity: sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==} + tar-stream@2.2.0: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} @@ -4466,6 +4715,12 @@ packages: engines: {node: '>=10'} hasBin: true + testcontainers@10.24.2: + resolution: {integrity: sha512-Don3EXEQuSw14+nFG9pj48fL9ck/jXDfR9Rb0K3acOyn/gg97+gsnfZaLzpdejl9GcPJVKxACNRe3SYVC2uWqg==} + + text-decoder@1.2.3: + resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} + text-extensions@2.4.0: resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} engines: {node: '>=8'} @@ -4497,6 +4752,10 @@ packages: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} + tmp@0.2.3: + resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} + engines: {node: '>=14.14'} + to-absolute-glob@3.0.0: resolution: {integrity: sha512-loO/XEWTRqpfcpI7+Jr2RR2Umaaozx1t6OSVWtMi0oy5F/Fxg3IC+D/TToDnxyAGs7uZBGT/6XmyDUxgsObJXA==} engines: {node: '>=0.10.0'} @@ -4591,6 +4850,9 @@ packages: resolution: {integrity: sha512-+6+hcWr4nwuESlKqUc626HMOTd3QT8hUOc9QM45PP1d4nErGkNOgExm4Pcov3in7LTuadMnB0gcd/BuzkEDIPw==} hasBin: true + tweetnacl@0.14.5: + resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -4663,6 +4925,10 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici@5.29.0: + resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} + engines: {node: '>=14.0'} + unherit@3.0.1: resolution: {integrity: sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg==} @@ -4746,6 +5012,10 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} @@ -5028,6 +5298,10 @@ packages: resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} engines: {node: '>=12.20'} + zip-stream@6.0.1: + resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} + engines: {node: '>= 14'} + zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} @@ -5336,6 +5610,8 @@ snapshots: '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 + '@balena/dockerignore@1.0.2': {} + '@changesets/apply-release-plan@7.0.0': dependencies: '@babel/runtime': 7.23.2 @@ -5804,6 +6080,20 @@ snapshots: hastscript: 7.2.0 unist-util-visit-parents: 5.1.3 + '@fastify/busboy@2.1.1': {} + + '@grpc/grpc-js@1.13.3': + dependencies: + '@grpc/proto-loader': 0.7.15 + '@js-sdsl/ordered-map': 4.4.2 + + '@grpc/proto-loader@0.7.15': + dependencies: + lodash.camelcase: 4.3.0 + long: 5.2.3 + protobufjs: 7.5.0 + yargs: 17.7.2 + '@humanwhocodes/config-array@0.11.13': dependencies: '@humanwhocodes/object-schema': 2.0.1 @@ -5869,6 +6159,8 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 + '@js-sdsl/ordered-map@4.4.2': {} + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.23.2 @@ -5954,6 +6246,29 @@ snapshots: picocolors: 1.0.0 tslib: 2.6.2 + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + '@rollup/rollup-android-arm-eabi@4.9.0': optional: true @@ -6030,6 +6345,17 @@ snapshots: dependencies: '@types/ms': 0.7.34 + '@types/docker-modem@3.0.6': + dependencies: + '@types/node': 20.10.4 + '@types/ssh2': 1.15.5 + + '@types/dockerode@3.3.38': + dependencies: + '@types/docker-modem': 3.0.6 + '@types/node': 20.10.4 + '@types/ssh2': 1.15.5 + '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 8.56.10 @@ -6081,6 +6407,10 @@ snapshots: '@types/node@17.0.45': {} + '@types/node@18.19.86': + dependencies: + undici-types: 5.26.5 + '@types/node@20.10.4': dependencies: undici-types: 5.26.5 @@ -6103,6 +6433,19 @@ snapshots: '@types/semver@7.5.5': {} + '@types/ssh2-streams@0.1.12': + dependencies: + '@types/node': 20.10.4 + + '@types/ssh2@0.5.52': + dependencies: + '@types/node': 20.10.4 + '@types/ssh2-streams': 0.1.12 + + '@types/ssh2@1.15.5': + dependencies: + '@types/node': 18.19.86 + '@types/unist@2.0.10': {} '@types/unist@3.0.2': {} @@ -6416,6 +6759,26 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 + archiver-utils@5.0.2: + dependencies: + glob: 10.3.10 + graceful-fs: 4.2.11 + is-stream: 2.0.1 + lazystream: 1.0.1 + lodash: 4.17.21 + normalize-path: 3.0.0 + readable-stream: 4.4.2 + + archiver@7.0.1: + dependencies: + archiver-utils: 5.0.2 + async: 3.2.6 + buffer-crc32: 1.0.0 + readable-stream: 4.4.2 + readdir-glob: 1.1.3 + tar-stream: 3.1.6 + zip-stream: 6.0.1 + arg@5.0.2: {} argparse@1.0.10: @@ -6478,6 +6841,10 @@ snapshots: arrify@3.0.0: {} + asn1@0.2.6: + dependencies: + safer-buffer: 2.1.2 + astring@1.8.6: {} astro-expressive-code@0.29.4(astro@4.0.5(@types/node@20.12.14)(terser@5.31.1)(typescript@5.5.2)): @@ -6561,6 +6928,10 @@ snapshots: - terser - typescript + async-lock@1.4.1: {} + + async@3.2.6: {} + atomic-sleep@1.0.0: {} autoprefixer@10.4.16(postcss@8.4.32): @@ -6581,6 +6952,31 @@ snapshots: balanced-match@1.0.2: {} + bare-events@2.5.4: + optional: true + + bare-fs@4.1.2: + dependencies: + bare-events: 2.5.4 + bare-path: 3.0.0 + bare-stream: 2.6.5(bare-events@2.5.4) + optional: true + + bare-os@3.6.1: + optional: true + + bare-path@3.0.0: + dependencies: + bare-os: 3.6.1 + optional: true + + bare-stream@2.6.5(bare-events@2.5.4): + dependencies: + streamx: 2.22.0 + optionalDependencies: + bare-events: 2.5.4 + optional: true + base-64@1.0.0: {} base64-js@1.5.1: {} @@ -6593,6 +6989,10 @@ snapshots: is-alphanumerical: 2.0.1 is-decimal: 2.0.1 + bcrypt-pbkdf@1.0.2: + dependencies: + tweetnacl: 0.14.5 + better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2 @@ -6661,6 +7061,8 @@ snapshots: node-releases: 2.0.14 update-browserslist-db: 1.0.16(browserslist@4.23.1) + buffer-crc32@1.0.0: {} + buffer-from@1.1.2: {} buffer@5.7.1: @@ -6673,6 +7075,9 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 + buildcheck@0.0.6: + optional: true + builtin-modules@3.3.0: {} builtins@5.0.1: @@ -6693,6 +7098,8 @@ snapshots: dependencies: run-applescript: 5.0.0 + byline@5.0.0: {} + call-bind@1.0.5: dependencies: function-bind: 1.1.2 @@ -6838,6 +7245,14 @@ snapshots: array-ify: 1.0.0 dot-prop: 5.3.0 + compress-commons@6.0.2: + dependencies: + crc-32: 1.2.2 + crc32-stream: 6.0.0 + is-stream: 2.0.1 + normalize-path: 3.0.0 + readable-stream: 4.4.2 + concat-map@0.0.1: {} confusing-browser-globals@1.0.11: {} @@ -6861,6 +7276,8 @@ snapshots: cookie@0.6.0: {} + core-util-is@1.0.3: {} + cosmiconfig-typescript-loader@5.0.0(@types/node@20.10.4)(cosmiconfig@8.3.6(typescript@5.5.2))(typescript@5.5.2): dependencies: '@types/node': 20.10.4 @@ -6886,6 +7303,19 @@ snapshots: optionalDependencies: typescript: 5.5.2 + cpu-features@0.0.10: + dependencies: + buildcheck: 0.0.6 + nan: 2.22.2 + optional: true + + crc-32@1.2.2: {} + + crc32-stream@6.0.0: + dependencies: + crc-32: 1.2.2 + readable-stream: 4.4.2 + cross-spawn@5.1.0: dependencies: lru-cache: 4.1.5 @@ -6937,6 +7367,10 @@ snapshots: dependencies: ms: 2.1.2 + debug@4.4.0: + dependencies: + ms: 2.1.3 + decamelize-keys@1.1.1: dependencies: decamelize: 1.2.0 @@ -7018,6 +7452,31 @@ snapshots: dlv@1.1.3: {} + docker-compose@0.24.8: + dependencies: + yaml: 2.3.4 + + docker-modem@5.0.6: + dependencies: + debug: 4.4.0 + readable-stream: 3.6.2 + split-ca: 1.0.1 + ssh2: 1.16.0 + transitivePeerDependencies: + - supports-color + + dockerode@4.0.6: + dependencies: + '@balena/dockerignore': 1.0.2 + '@grpc/grpc-js': 1.13.3 + '@grpc/proto-loader': 0.7.15 + docker-modem: 5.0.6 + protobufjs: 7.5.0 + tar-fs: 2.1.2 + uuid: 10.0.0 + transitivePeerDependencies: + - supports-color + doctrine@2.1.0: dependencies: esutils: 2.0.3 @@ -7243,12 +7702,12 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.27.5)(webpack@5.90.1): + eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint@8.53.0))(webpack@5.90.1): dependencies: array.prototype.find: 2.2.2 debug: 3.2.7 enhanced-resolve: 0.9.1 - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint-import-resolver-webpack@0.13.8)(eslint@8.53.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint@8.53.0))(webpack@5.90.1))(eslint@8.53.0) find-root: 1.1.0 hasown: 2.0.1 interpret: 1.4.0 @@ -7261,14 +7720,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.27.5)(webpack@5.90.1))(eslint@8.53.0): + eslint-module-utils@2.8.0(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint@8.53.0))(webpack@5.90.1))(eslint@8.53.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 6.10.0(eslint@8.53.0)(typescript@5.5.2) eslint: 8.53.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-webpack: 0.13.8(eslint-plugin-import@2.27.5)(webpack@5.90.1) + eslint-import-resolver-webpack: 0.13.8(eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint@8.53.0))(webpack@5.90.1) transitivePeerDependencies: - supports-color @@ -7296,7 +7755,7 @@ snapshots: eslint: 8.53.0 ignore: 5.2.4 - eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint-import-resolver-webpack@0.13.8)(eslint@8.53.0): + eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint@8.53.0))(webpack@5.90.1))(eslint@8.53.0): dependencies: array-includes: 3.1.7 array.prototype.flat: 1.3.2 @@ -7305,7 +7764,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.53.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.27.5)(webpack@5.90.1))(eslint@8.53.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint@8.53.0))(webpack@5.90.1))(eslint@8.53.0) has: 1.0.4 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -7687,6 +8146,8 @@ snapshots: has-symbols: 1.0.3 hasown: 2.0.0 + get-port@7.1.0: {} + get-set-props@0.1.0: {} get-stdin@9.0.0: {} @@ -8304,6 +8765,8 @@ snapshots: dependencies: is-inside-container: 1.0.0 + isarray@1.0.0: {} + isarray@2.0.5: {} isexe@2.0.0: {} @@ -8379,6 +8842,10 @@ snapshots: kleur@4.1.5: {} + lazystream@1.0.1: + dependencies: + readable-stream: 2.3.8 + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -9045,6 +9512,10 @@ snapshots: dependencies: brace-expansion: 1.1.11 + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + minimatch@9.0.3: dependencies: brace-expansion: 2.0.1 @@ -9063,10 +9534,14 @@ snapshots: mkdirp-classic@0.5.3: {} + mkdirp@1.0.4: {} + ms@2.0.0: {} ms@2.1.2: {} + ms@2.1.3: {} + muggle-string@0.4.1: {} mysql2@3.6.5: @@ -9090,6 +9565,9 @@ snapshots: dependencies: lru-cache: 7.18.3 + nan@2.22.2: + optional: true + nanoid@3.3.7: {} napi-build-utils@1.0.2: {} @@ -9515,6 +9993,8 @@ snapshots: transitivePeerDependencies: - supports-color + process-nextick-args@2.0.1: {} + process-warning@2.3.2: {} process@0.11.10: {} @@ -9524,10 +10004,35 @@ snapshots: kleur: 3.0.3 sisteransi: 1.0.5 + proper-lockfile@4.1.2: + dependencies: + graceful-fs: 4.2.11 + retry: 0.12.0 + signal-exit: 3.0.7 + + properties-reader@2.3.0: + dependencies: + mkdirp: 1.0.4 + property-information@6.4.0: {} proto-props@2.0.0: {} + protobufjs@7.5.0: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 20.10.4 + long: 5.2.3 + pseudomap@1.0.2: {} pump@3.0.0: @@ -9586,6 +10091,16 @@ snapshots: pify: 4.0.1 strip-bom: 3.0.0 + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 @@ -9600,6 +10115,10 @@ snapshots: process: 0.11.10 string_decoder: 1.3.0 + readdir-glob@1.1.3: + dependencies: + minimatch: 5.1.6 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -9774,6 +10293,8 @@ snapshots: retext-stringify: 3.1.0 unified: 10.1.2 + retry@0.12.0: {} + reusify@1.0.4: {} rfdc@1.3.0: {} @@ -9814,6 +10335,8 @@ snapshots: has-symbols: 1.0.3 isarray: 2.0.5 + safe-buffer@5.1.2: {} + safe-buffer@5.2.1: {} safe-regex-test@1.0.0: @@ -10006,6 +10529,8 @@ snapshots: spdx-license-ids@3.0.16: {} + split-ca@1.0.1: {} + split2@3.2.2: dependencies: readable-stream: 3.6.2 @@ -10016,6 +10541,19 @@ snapshots: sqlstring@2.3.3: {} + ssh-remote-port-forward@1.0.4: + dependencies: + '@types/ssh2': 0.5.52 + ssh2: 1.16.0 + + ssh2@1.16.0: + dependencies: + asn1: 0.2.6 + bcrypt-pbkdf: 1.0.2 + optionalDependencies: + cpu-features: 0.0.10 + nan: 2.22.2 + stdin-discarder@0.1.0: dependencies: bl: 5.1.0 @@ -10035,6 +10573,14 @@ snapshots: fast-fifo: 1.3.2 queue-tick: 1.0.1 + streamx@2.22.0: + dependencies: + fast-fifo: 1.3.2 + text-decoder: 1.2.3 + optionalDependencies: + bare-events: 2.5.4 + optional: true + string-argv@0.3.2: {} string-width@4.2.3: @@ -10091,6 +10637,10 @@ snapshots: define-properties: 1.2.1 es-abstract: 1.22.3 + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 @@ -10204,12 +10754,29 @@ snapshots: pump: 3.0.0 tar-stream: 2.2.0 + tar-fs@2.1.2: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 2.2.0 + tar-fs@3.0.4: dependencies: mkdirp-classic: 0.5.3 pump: 3.0.0 tar-stream: 3.1.6 + tar-fs@3.0.8: + dependencies: + pump: 3.0.0 + tar-stream: 3.1.6 + optionalDependencies: + bare-fs: 4.1.2 + bare-path: 3.0.0 + transitivePeerDependencies: + - bare-buffer + tar-stream@2.2.0: dependencies: bl: 4.1.0 @@ -10242,6 +10809,32 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 + testcontainers@10.24.2: + dependencies: + '@balena/dockerignore': 1.0.2 + '@types/dockerode': 3.3.38 + archiver: 7.0.1 + async-lock: 1.4.1 + byline: 5.0.0 + debug: 4.4.0 + docker-compose: 0.24.8 + dockerode: 4.0.6 + get-port: 7.1.0 + proper-lockfile: 4.1.2 + properties-reader: 2.3.0 + ssh-remote-port-forward: 1.0.4 + tar-fs: 3.0.8 + tmp: 0.2.3 + undici: 5.29.0 + transitivePeerDependencies: + - bare-buffer + - supports-color + + text-decoder@1.2.3: + dependencies: + b4a: 1.6.4 + optional: true + text-extensions@2.4.0: {} text-table@0.2.0: {} @@ -10270,6 +10863,8 @@ snapshots: dependencies: os-tmpdir: 1.0.2 + tmp@0.2.3: {} + to-absolute-glob@3.0.0: dependencies: is-absolute: 1.0.0 @@ -10354,6 +10949,8 @@ snapshots: turbo-windows-64: 2.0.5 turbo-windows-arm64: 2.0.5 + tweetnacl@0.14.5: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -10420,6 +11017,10 @@ snapshots: undici-types@5.26.5: {} + undici@5.29.0: + dependencies: + '@fastify/busboy': 2.1.1 + unherit@3.0.1: {} unified@10.1.2: @@ -10536,6 +11137,8 @@ snapshots: util-deprecate@1.0.2: {} + uuid@10.0.0: {} + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 @@ -10797,10 +11400,10 @@ snapshots: eslint-config-xo: 0.43.1(eslint@8.53.0) eslint-config-xo-typescript: 1.0.1(@typescript-eslint/eslint-plugin@6.10.0(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint@8.53.0)(typescript@5.5.2))(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint@8.53.0)(typescript@5.5.2) eslint-formatter-pretty: 5.0.0 - eslint-import-resolver-webpack: 0.13.8(eslint-plugin-import@2.27.5)(webpack@5.90.1) + eslint-import-resolver-webpack: 0.13.8(eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint@8.53.0))(webpack@5.90.1) eslint-plugin-ava: 14.0.0(eslint@8.53.0) eslint-plugin-eslint-comments: 3.2.0(eslint@8.53.0) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint-import-resolver-webpack@0.13.8)(eslint@8.53.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.10.0(eslint@8.53.0)(typescript@5.5.2))(eslint@8.53.0))(webpack@5.90.1))(eslint@8.53.0) eslint-plugin-n: 16.3.0(eslint@8.53.0) eslint-plugin-no-use-extend-native: 0.5.0 eslint-plugin-prettier: 5.0.1(@types/eslint@8.56.10)(eslint-config-prettier@8.10.0(eslint@8.53.0))(eslint@8.53.0)(prettier@3.1.1) @@ -10878,6 +11481,12 @@ snapshots: yocto-queue@1.0.0: {} + zip-stream@6.0.1: + dependencies: + archiver-utils: 5.0.2 + compress-commons: 6.0.2 + readable-stream: 4.4.2 + zod@3.22.4: {} zwitch@2.0.4: {}