diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index ddf92ba..70198b6 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -103,3 +103,21 @@ jobs: node-version: 24.10.0 - name: Check for circular dependencies run: pnpm circular + + integration: + name: Integration Tests + runs-on: ubuntu-latest + permissions: + contents: read + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - name: Install dependencies + uses: ./.github/actions/setup + with: + node-version: 24.10.0 + - name: Run integration tests + run: pnpm test:integration + - name: Collect container logs on failure + if: failure() + run: docker compose -p amp-integration-tests logs --tail 200 2>/dev/null || true diff --git a/.gitignore b/.gitignore index 8c572a9..e749375 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,9 @@ scratchpad/**/*.md scratchpad/**/*.ts !scratchpad/index.ts +# Agent Context +.repos/ + # Generated by foundry out/ broadcast/ diff --git a/docker-compose.yml b/docker-compose.yml index d5e9b10..95ab3c0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,7 +23,7 @@ services: anvil: image: ghcr.io/foundry-rs/foundry - entrypoint: ["anvil", "--host", "0.0.0.0"] + entrypoint: ["anvil", "--host", "0.0.0.0", "--block-time", "1"] ports: - 8545:8545 @@ -54,7 +54,7 @@ services: # Amp is a data engineering layer for Ethereum. # https://github.com/edgeandnode/amp amp: - image: ghcr.io/edgeandnode/amp:latest + image: ghcr.io/edgeandnode/amp:canary command: ["--config", "/var/lib/amp/config.toml", "dev"] depends_on: - postgres diff --git a/package.json b/package.json index 9cb0540..af1d677 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "clean": "node scripts/clean.mjs", "lint": "oxlint && dprint check", "lint:fix": "oxlint --fix && dprint fmt", - "test": "vitest" + "test": "vitest", + "test:integration": "pnpm --filter @edgeandnode/amp test:integration" }, "pnpm": { "overrides": { @@ -41,6 +42,7 @@ "madge": "^8.0.0", "oxlint": "^1.42.0", "rulesync": "^6.7.0", + "testcontainers": "^11.12.0", "ts-patch": "^3.3.0", "typescript": "^5.9.3", "vite-tsconfig-paths": "^6.0.5", diff --git a/packages/amp/package.json b/packages/amp/package.json index aee27fc..aa51173 100644 --- a/packages/amp/package.json +++ b/packages/amp/package.json @@ -39,6 +39,7 @@ "babel": "babel dist --plugins annotate-pure-calls --out-dir dist --source-maps", "check": "tsc -b tsconfig.json", "test": "vitest", + "test:integration": "vitest run --config vitest.integration.config.ts", "coverage": "vitest --coverage" }, "peerDependencies": { diff --git a/packages/amp/src/admin/domain.ts b/packages/amp/src/admin/domain.ts index f6c5edb..c2c1586 100644 --- a/packages/amp/src/admin/domain.ts +++ b/packages/amp/src/admin/domain.ts @@ -60,7 +60,27 @@ export class GetDatasetVersionResponse extends Schema.Class( "Amp/AdminApi/GetDatasetVersionsResponse" )({ - versions: Schema.Array(Models.DatasetVersion) + namespace: Models.DatasetNamespace, + name: Models.DatasetName, + versions: Schema.Array(Schema.Struct({ + version: Models.DatasetVersion, + manifestHash: Models.DatasetHash.pipe( + Schema.propertySignature, + Schema.fromKey("manifest_hash") + ), + createdAt: Schema.DateTimeUtc.pipe( + Schema.propertySignature, + Schema.fromKey("created_at") + ), + updatedAt: Schema.DateTimeUtc.pipe( + Schema.propertySignature, + Schema.fromKey("updated_at") + ) + })), + specialTags: Schema.Struct({ + dev: Schema.optional(Schema.Union(Models.DatasetVersion, Models.DatasetHash)), + latest: Schema.optional(Schema.Union(Models.DatasetVersion, Models.DatasetHash)) + }).pipe(Schema.propertySignature, Schema.fromKey("special_tags")) }, { identifier: "GetDatasetVersionsResponse" }) {} /** diff --git a/packages/amp/test/integration/fixtures/anvil-manifest.ts b/packages/amp/test/integration/fixtures/anvil-manifest.ts new file mode 100644 index 0000000..55142b5 --- /dev/null +++ b/packages/amp/test/integration/fixtures/anvil-manifest.ts @@ -0,0 +1,213 @@ +/** + * Anvil evm-rpc manifest for integration tests. + */ +import type * as Models from "@edgeandnode/amp/core" + +const blocksFields: Array = [ + { name: "_block_num", type: "UInt64", nullable: false }, + { name: "block_num", type: "UInt64", nullable: false }, + { name: "timestamp", type: { Timestamp: ["Nanosecond", "+00:00"] }, nullable: false }, + { name: "hash", type: { FixedSizeBinary: 32 }, nullable: false }, + { name: "parent_hash", type: { FixedSizeBinary: 32 }, nullable: false }, + { name: "ommers_hash", type: { FixedSizeBinary: 32 }, nullable: false }, + { name: "miner", type: { FixedSizeBinary: 20 }, nullable: false }, + { name: "state_root", type: { FixedSizeBinary: 32 }, nullable: false }, + { name: "transactions_root", type: { FixedSizeBinary: 32 }, nullable: false }, + { name: "receipt_root", type: { FixedSizeBinary: 32 }, nullable: false }, + { name: "logs_bloom", type: "Binary", nullable: false }, + { name: "difficulty", type: { Decimal128: [38, 0] }, nullable: false }, + { name: "total_difficulty", type: { Decimal128: [38, 0] }, nullable: true }, + { name: "gas_limit", type: "UInt64", nullable: false }, + { name: "gas_used", type: "UInt64", nullable: false }, + { name: "extra_data", type: "Binary", nullable: false }, + { name: "mix_hash", type: { FixedSizeBinary: 32 }, nullable: false }, + { name: "nonce", type: "UInt64", nullable: false }, + { name: "base_fee_per_gas", type: { Decimal128: [38, 0] }, nullable: true }, + { name: "withdrawals_root", type: { FixedSizeBinary: 32 }, nullable: true }, + { name: "blob_gas_used", type: "UInt64", nullable: true }, + { name: "excess_blob_gas", type: "UInt64", nullable: true }, + { name: "parent_beacon_root", type: { FixedSizeBinary: 32 }, nullable: true }, + { name: "requests_hash", type: { FixedSizeBinary: 32 }, nullable: true } +] + +const transactionsFields: Array = [ + { name: "_block_num", type: "UInt64", nullable: false }, + { name: "block_hash", type: { FixedSizeBinary: 32 }, nullable: false }, + { name: "block_num", type: "UInt64", nullable: false }, + { name: "timestamp", type: { Timestamp: ["Nanosecond", "+00:00"] }, nullable: false }, + { name: "tx_index", type: "UInt32", nullable: false }, + { name: "tx_hash", type: { FixedSizeBinary: 32 }, nullable: false }, + { name: "to", type: { FixedSizeBinary: 20 }, nullable: true }, + { name: "nonce", type: "UInt64", nullable: false }, + { name: "gas_price", type: { Decimal128: [38, 0] }, nullable: true }, + { name: "gas_limit", type: "UInt64", nullable: false }, + { name: "value", type: "Utf8", nullable: false }, + { name: "input", type: "Binary", nullable: false }, + { name: "r", type: { FixedSizeBinary: 32 }, nullable: false }, + { name: "s", type: { FixedSizeBinary: 32 }, nullable: false }, + { name: "v_parity", type: "Boolean", nullable: false }, + { name: "chain_id", type: "UInt64", nullable: true }, + { name: "gas_used", type: "UInt64", nullable: false }, + { name: "type", type: "Int32", nullable: false }, + { name: "max_fee_per_gas", type: { Decimal128: [38, 0] }, nullable: true }, + { name: "max_priority_fee_per_gas", type: { Decimal128: [38, 0] }, nullable: true }, + { name: "max_fee_per_blob_gas", type: { Decimal128: [38, 0] }, nullable: true }, + { name: "from", type: { FixedSizeBinary: 20 }, nullable: false }, + { name: "status", type: "Boolean", nullable: false }, + { name: "state_root", type: { FixedSizeBinary: 32 }, nullable: true }, + { + name: "access_list", + type: { + List: { + name: "item", + nullable: false, + data_type: { + Struct: [ + { + name: "address", + nullable: false, + data_type: { FixedSizeBinary: 20 }, + dict_id: 0, + dict_is_ordered: false, + metadata: {} + }, + { + name: "storage_keys", + nullable: false, + data_type: { + List: { + name: "item", + nullable: false, + data_type: { FixedSizeBinary: 32 }, + dict_id: 0, + dict_is_ordered: false, + metadata: {} + } + }, + dict_id: 0, + dict_is_ordered: false, + metadata: {} + } + ] + }, + dict_id: 0, + dict_is_ordered: false, + metadata: {} + } + }, + nullable: true + }, + { + name: "blob_versioned_hashes", + type: { + List: { + name: "item", + nullable: false, + data_type: { FixedSizeBinary: 32 }, + dict_id: 0, + dict_is_ordered: false, + metadata: {} + } + }, + nullable: true + }, + { + name: "authorization_list", + type: { + List: { + name: "item", + nullable: false, + data_type: { + Struct: [ + { + name: "chain_id", + nullable: false, + data_type: "UInt64", + dict_id: 0, + dict_is_ordered: false, + metadata: {} + }, + { + name: "address", + nullable: false, + data_type: { FixedSizeBinary: 20 }, + dict_id: 0, + dict_is_ordered: false, + metadata: {} + }, + { + name: "nonce", + nullable: false, + data_type: "UInt64", + dict_id: 0, + dict_is_ordered: false, + metadata: {} + }, + { + name: "y_parity", + nullable: false, + data_type: "Boolean", + dict_id: 0, + dict_is_ordered: false, + metadata: {} + }, + { + name: "r", + nullable: false, + data_type: { FixedSizeBinary: 32 }, + dict_id: 0, + dict_is_ordered: false, + metadata: {} + }, + { + name: "s", + nullable: false, + data_type: { FixedSizeBinary: 32 }, + dict_id: 0, + dict_is_ordered: false, + metadata: {} + } + ] + }, + dict_id: 0, + dict_is_ordered: false, + metadata: {} + } + }, + nullable: true + } +] + +const logsFields: Array = [ + { name: "_block_num", type: "UInt64", nullable: false }, + { name: "block_hash", type: { FixedSizeBinary: 32 }, nullable: false }, + { name: "block_num", type: "UInt64", nullable: false }, + { name: "timestamp", type: { Timestamp: ["Nanosecond", "+00:00"] }, nullable: false }, + { name: "tx_hash", type: { FixedSizeBinary: 32 }, nullable: false }, + { name: "tx_index", type: "UInt32", nullable: false }, + { name: "log_index", type: "UInt32", nullable: false }, + { name: "address", type: { FixedSizeBinary: 20 }, nullable: false }, + { name: "topic0", type: { FixedSizeBinary: 32 }, nullable: true }, + { name: "topic1", type: { FixedSizeBinary: 32 }, nullable: true }, + { name: "topic2", type: { FixedSizeBinary: 32 }, nullable: true }, + { name: "topic3", type: { FixedSizeBinary: 32 }, nullable: true }, + { name: "data", type: "Binary", nullable: false } +] + +const network = "anvil" as Models.Network + +/** + * Anvil evm-rpc manifest — typed as `DatasetManifest` for direct use with + * `AdminApi.registerDataset`. + */ +export const anvilManifest: Models.DatasetManifest = { + kind: "evm-rpc", + network, + startBlock: 0, + finalizedBlocksOnly: false, + tables: { + blocks: { schema: { arrow: { fields: blocksFields } }, network }, + transactions: { schema: { arrow: { fields: transactionsFields } }, network }, + logs: { schema: { arrow: { fields: logsFields } }, network } + } +} diff --git a/packages/amp/test/integration/helpers.ts b/packages/amp/test/integration/helpers.ts new file mode 100644 index 0000000..7d35520 --- /dev/null +++ b/packages/amp/test/integration/helpers.ts @@ -0,0 +1,75 @@ +import * as AdminService from "@edgeandnode/amp/admin/service" +import * as Models from "@edgeandnode/amp/core" +import * as Effect from "effect/Effect" + +/** + * Generate a unique dataset name for test isolation. + * Each test group gets its own name so tests don't collide. + */ +export const uniqueDatasetName = (prefix: string): Models.DatasetName => + Models.DatasetName.make(`${prefix}_${Date.now()}`) + +/** Terminal job statuses — polling stops when the job reaches one of these. */ +const TERMINAL_STATUSES = new Set(["COMPLETED", "STOPPED", "FAILED", "UNKNOWN"]) + +/** + * Poll job status until it reaches a terminal state. + * Polls up to 15 times with 1-second spacing (15s total). + * Returns the final `JobInfo`. + */ +export const waitForJob = Effect.fn(function*(jobId: number) { + const admin = yield* AdminService.AdminApi + + for (let attempt = 1; attempt <= 15; attempt++) { + if (attempt > 1) { + yield* Effect.sleep("1 second") + } + const job = yield* admin.getJobById(jobId) + if (TERMINAL_STATUSES.has(job.status)) { + return job + } + } + + return yield* Effect.die( + new Error( + `Job ${jobId} did not reach terminal state after 15 attempts` + ) + ) +}) + +/** + * Poll sync progress until at least one table has blocks. + * Polls up to 60 times with 2-second spacing (120s total). + * + * Resilient to transient errors — the sync progress endpoint may not + * be available immediately after job completion (the SDK converts some + * API errors to defects via `Effect.die`). + */ +export const waitForSync = Effect.fn( + function*( + namespace: Models.DatasetNamespace, + name: Models.DatasetName, + revision: Models.DatasetRevision + ) { + const admin = yield* AdminService.AdminApi + + for (let attempt = 1; attempt <= 60; attempt++) { + if (attempt > 1) { + yield* Effect.sleep("2 seconds") + } + const synced = yield* admin.getDatasetSyncProgress(namespace, name, revision).pipe( + Effect.map((progress) => progress.tables.some((t) => t.currentBlock !== undefined && t.currentBlock > 0)), + Effect.catchAllCause(() => Effect.succeed(false)) + ) + if (synced) { + return + } + } + + return yield* Effect.die( + new Error( + "Sync progress did not show blocks after 60 attempts" + ) + ) + } +) diff --git a/packages/amp/test/integration/integration.test.ts b/packages/amp/test/integration/integration.test.ts new file mode 100644 index 0000000..7fc8537 --- /dev/null +++ b/packages/amp/test/integration/integration.test.ts @@ -0,0 +1,360 @@ +import { AdminApi } from "@edgeandnode/amp/admin/service" +import { ArrowFlight } from "@edgeandnode/amp/arrow-flight" +import * as Models from "@edgeandnode/amp/core" +import { describe, expect, layer } from "@effect/vitest" +import * as Context from "effect/Context" +import * as Effect from "effect/Effect" +import * as Exit from "effect/Exit" +import * as Layer from "effect/Layer" +import { anvilManifest } from "./fixtures/anvil-manifest.ts" +import { waitForJob } from "./helpers.ts" +import { IntegrationLayer } from "./layers.ts" + +// ============================================================================= +// Dataset Fixture — registers and deploys an Anvil dataset once +// ============================================================================= + +const NAMESPACE = Models.DatasetNamespace.make("_") +const DATASET_NAME = Models.DatasetName.make("anvil") +const REVISION = Models.DatasetTag.make("latest") +const VERSION = Models.DatasetVersion.make("1.0.0") + +/** + * Shared fixture exposing the dataset reference and job ID from a single + * register -> deploy -> wait cycle. Built once per test suite via a Layer. + */ +class DatasetFixture extends Context.Tag("Test/DatasetFixture")() {} + +const DatasetFixtureLayer = Layer.effect( + DatasetFixture, + Effect.gen(function*() { + const admin = yield* AdminApi + + // Register with explicit version so "latest" tag is created + yield* admin.registerDataset(NAMESPACE, DATASET_NAME, anvilManifest, VERSION) + + // Deploy with finite endBlock so the job completes + const { jobId } = yield* admin.deployDataset(NAMESPACE, DATASET_NAME, REVISION, { + endBlock: "5" + }) + + // Wait for the job to reach a terminal state + const job = yield* waitForJob(jobId) + if (job.status !== "COMPLETED") { + return yield* Effect.die( + new Error(`Expected job ${jobId} to complete, got status: ${job.status}`) + ) + } + + // Brief pause to allow data to become queryable after job completion + yield* Effect.sleep("2 seconds") + + return DatasetFixture.of({ + namespace: NAMESPACE, + name: DATASET_NAME, + revision: REVISION, + jobId + }) + }) +) + +/** + * Full integration layer that includes the dataset fixture. + * The fixture depends on AdminApi (from IntegrationLayer) and + * registers/deploys once before all tests in its scope. + */ +const FullIntegrationLayer = DatasetFixtureLayer.pipe( + Layer.provideMerge(IntegrationLayer) +) + +// ============================================================================= +// Helpers +// ============================================================================= + +/** + * Collect all rows from a query result. `flight.query` returns an array of + * `QueryResult` batches, each with a `data` array of rows. This flattens + * them into a single array. + */ +const collectRows = (batches: ReadonlyArray<{ readonly data: ReadonlyArray }>): Array => + batches.flatMap((b) => b.data) + +// ============================================================================= +// Tests +// ============================================================================= + +layer(FullIntegrationLayer, { + timeout: "3 minutes", + excludeTestServices: true +})("Integration", (it) => { + // =========================================================================== + // Tier 1-2: Smoke Tests + // =========================================================================== + + describe("AdminApi smoke tests", () => { + it.effect("getProviders returns configured providers", () => + Effect.gen(function*() { + const admin = yield* AdminApi + const response = yield* admin.getProviders + expect(response.providers.length).toBeGreaterThan(0) + // The Anvil provider should be present + const anvil = response.providers.find((p) => p.network === "anvil") + expect(anvil).toBeDefined() + })) + + it.effect("getDatasets returns a list", () => + Effect.gen(function*() { + const admin = yield* AdminApi + const response = yield* admin.getDatasets + expect(response.datasets).toBeInstanceOf(Array) + })) + + it.effect("getWorkers returns a list", () => + Effect.gen(function*() { + const admin = yield* AdminApi + const response = yield* admin.getWorkers + expect(response).toBeDefined() + })) + + it.effect("getJobs returns a list", () => + Effect.gen(function*() { + const admin = yield* AdminApi + const response = yield* admin.getJobs() + expect(response.jobs).toBeInstanceOf(Array) + })) + }) + + describe("ArrowFlight smoke tests", () => { + it.effect("executes a simple SQL query", () => + Effect.gen(function*() { + const flight = yield* ArrowFlight + const batches = yield* flight.query("SELECT 1 AS value") + const rows = collectRows(batches) + expect(rows.length).toBeGreaterThan(0) + })) + }) + + // =========================================================================== + // Tier 3: Dataset Lifecycle — Query Validation + // =========================================================================== + + describe("Dataset lifecycle: query validation", () => { + it.effect("queries anvil.blocks and validates structure", () => + Effect.gen(function*() { + const fixture = yield* DatasetFixture + const flight = yield* ArrowFlight + const batches = yield* flight.query( + `SELECT block_num, hash, parent_hash, timestamp FROM ${fixture.name}.blocks ORDER BY block_num ASC` + ) + const rows = collectRows(batches) + + // Should have at least one block (blocks 0-5) + expect(rows.length).toBeGreaterThan(0) + + // Validate first row structure + const first = rows[0] + expect(first).toHaveProperty("block_num") + expect(first).toHaveProperty("hash") + expect(first).toHaveProperty("parent_hash") + expect(first).toHaveProperty("timestamp") + })) + + it.effect("queries anvil.blocks and validates sequential block numbers", () => + Effect.gen(function*() { + const fixture = yield* DatasetFixture + const flight = yield* ArrowFlight + const batches = yield* flight.query( + `SELECT block_num FROM ${fixture.name}.blocks ORDER BY block_num ASC` + ) + const rows = collectRows(batches) + + expect(rows.length).toBeGreaterThan(0) + + // Block numbers should be sequential starting from 0 + for (let i = 0; i < rows.length; i++) { + expect(Number(rows[i]!.block_num)).toBe(i) + } + })) + + it.effect("queries anvil.transactions table", () => + Effect.gen(function*() { + const fixture = yield* DatasetFixture + const flight = yield* ArrowFlight + const batches = yield* flight.query( + `SELECT block_num, tx_hash, tx_index FROM ${fixture.name}.transactions ORDER BY block_num ASC, tx_index ASC` + ) + const rows = collectRows(batches) + + // Anvil with --block-time mines empty blocks, so transactions may be empty. + // Validate structure only if rows exist. + expect(rows).toBeInstanceOf(Array) + + if (rows.length > 0) { + const first = rows[0] + expect(first).toHaveProperty("block_num") + expect(first).toHaveProperty("tx_hash") + expect(first).toHaveProperty("tx_index") + } + })) + + it.effect("queries anvil.logs and validates structure", () => + Effect.gen(function*() { + const fixture = yield* DatasetFixture + const flight = yield* ArrowFlight + const batches = yield* flight.query( + `SELECT block_num, log_index, address, topic0, data FROM ${fixture.name}.logs ORDER BY block_num ASC, log_index ASC` + ) + const rows = collectRows(batches) + + // May or may not have logs depending on Anvil setup, but query should succeed + expect(rows).toBeInstanceOf(Array) + + if (rows.length > 0) { + const first = rows[0] + expect(first).toHaveProperty("block_num") + expect(first).toHaveProperty("log_index") + expect(first).toHaveProperty("address") + } + })) + + it.effect("queries block count and validates range", () => + Effect.gen(function*() { + const fixture = yield* DatasetFixture + const flight = yield* ArrowFlight + const batches = yield* flight.query( + `SELECT COUNT(*) AS cnt FROM ${fixture.name}.blocks` + ) + const rows = collectRows(batches) + + expect(rows.length).toBe(1) + const count = Number(rows[0]!.cnt) + // endBlock=5 means blocks 0-5 = 6 blocks + expect(count).toBeGreaterThanOrEqual(1) + expect(count).toBeLessThanOrEqual(6) + })) + }) + + // =========================================================================== + // Tier 3: Dataset Lifecycle — Job & Metadata + // =========================================================================== + + describe("Dataset lifecycle: job inspection", () => { + it.effect("getJobById returns the deployment job", () => + Effect.gen(function*() { + const fixture = yield* DatasetFixture + const admin = yield* AdminApi + const job = yield* admin.getJobById(fixture.jobId) + + expect(job.id).toBe(fixture.jobId) + expect(job.status).toBe("COMPLETED") + })) + + // Server bug: GET /jobs without a status filter returns an empty array + // even when jobs exist. GET /jobs?status=COMPLETED returns them fine, + // and getJobById also succeeds. When the server is fixed, this test + // should assert jobs.length > 0 and find a COMPLETED job. + it.effect("getJobs returns empty without status filter", () => + Effect.gen(function*() { + const admin = yield* AdminApi + const response = yield* admin.getJobs() + + // Succeeds but returns no jobs unless a status filter is provided + expect(response.jobs).toBeInstanceOf(Array) + expect(response.jobs.length).toBe(0) + })) + }) + + describe("Dataset lifecycle: metadata readback", () => { + it.effect("getDatasets includes the registered dataset", () => + Effect.gen(function*() { + const fixture = yield* DatasetFixture + const admin = yield* AdminApi + const response = yield* admin.getDatasets + + const found = response.datasets.find( + (d) => d.namespace === fixture.namespace && d.name === fixture.name + ) + expect(found).toBeDefined() + })) + + it.effect("getDatasetVersion returns version info", () => + Effect.gen(function*() { + const fixture = yield* DatasetFixture + const admin = yield* AdminApi + const version = yield* admin.getDatasetVersion( + fixture.namespace, + fixture.name, + fixture.revision + ) + + expect(version.kind).toBe("evm-rpc") + expect(version.namespace).toBe(fixture.namespace) + expect(version.name).toBe(fixture.name) + })) + + it.effect("getDatasetManifest returns the registered manifest", () => + Effect.gen(function*() { + const fixture = yield* DatasetFixture + const admin = yield* AdminApi + const manifest = yield* admin.getDatasetManifest( + fixture.namespace, + fixture.name, + fixture.revision + ) + + expect(manifest.kind).toBe("evm-rpc") + if (manifest.kind === "evm-rpc") { + expect(manifest.network).toBe("anvil") + expect(Object.keys(manifest.tables)).toContain("blocks") + expect(Object.keys(manifest.tables)).toContain("transactions") + expect(Object.keys(manifest.tables)).toContain("logs") + } + })) + + it.effect("getDatasetVersions returns version info", () => + Effect.gen(function*() { + const fixture = yield* DatasetFixture + const admin = yield* AdminApi + const response = yield* admin.getDatasetVersions( + fixture.namespace, + fixture.name + ) + + expect(response.namespace).toBe(fixture.namespace) + expect(response.name).toBe(fixture.name) + expect(response.versions.length).toBeGreaterThan(0) + + const first = response.versions[0]! + expect(first.version).toBe(VERSION) + expect(first.manifestHash).toBeDefined() + expect(first.createdAt).toBeDefined() + expect(first.updatedAt).toBeDefined() + + // Special tags should map "latest" to our version + expect(response.specialTags.latest).toBe(VERSION) + })) + + // Server bug: GET /datasets/:ns/:name/versions/:rev/sync-progress + // returns HTTP 404 with an empty body. The SDK can't decode the empty + // response into either the success or error schema, causing a ParseError + // defect. When the server is fixed, this test should validate sync + // progress tables. + it.effect("getDatasetSyncProgress fails due to server 404 with empty body", () => + Effect.gen(function*() { + const fixture = yield* DatasetFixture + const admin = yield* AdminApi + const exit = yield* admin.getDatasetSyncProgress( + fixture.namespace, + fixture.name, + fixture.revision + ).pipe(Effect.exit) + + expect(Exit.isFailure(exit)).toBe(true) + })) + }) +}) diff --git a/packages/amp/test/integration/layers.ts b/packages/amp/test/integration/layers.ts new file mode 100644 index 0000000..b914aa0 --- /dev/null +++ b/packages/amp/test/integration/layers.ts @@ -0,0 +1,82 @@ +import * as AdminService from "@edgeandnode/amp/admin/service" +import * as ArrowFlight from "@edgeandnode/amp/arrow-flight" +import * as ArrowFlightNode from "@edgeandnode/amp/arrow-flight/node" +import * as NodeContext from "@effect/platform-node/NodeContext" +import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient" +import * as FileSystem from "@effect/platform/FileSystem" +import * as Path from "@effect/platform/Path" +import * as Effect from "effect/Effect" +import * as Layer from "effect/Layer" +import { DockerComposeEnvironment, Wait } from "testcontainers" + +const AMP_ADMIN_URL = "http://localhost:1610" +const AMP_FLIGHT_URL = "http://localhost:1602" + +/** + * Resolve the monorepo root from `import.meta.dirname` (which is `packages/amp/test/integration/`). + * Four levels up: integration → test → amp → packages → root. + */ +const resolveProjectRoot = Effect.fn("resolveProjectRoot")(function*() { + const path = yield* Path.Path + return path.resolve(import.meta.dirname, "../../../..") +}) + +/** + * Ensure required Amp infrastructure directories exist and are clean. + * Amp mounts these as volumes — stale data from previous runs can + * cause the server to enter a conflicting state. + */ +const ensureCleanDirectories = Effect.fn("ensureCleanDirectories")(function*(projectRoot: string) { + const fs = yield* FileSystem.FileSystem + const path = yield* Path.Path + const dataDirs = [ + path.join(projectRoot, "infra/amp/data"), + path.join(projectRoot, "infra/amp/datasets") + ] + for (const dir of dataDirs) { + yield* fs.remove(dir, { recursive: true }).pipe(Effect.ignore) + yield* fs.makeDirectory(dir, { recursive: true }) + } +}) + +const DockerComposeLayer = Layer.scopedDiscard( + Effect.acquireRelease( + Effect.gen(function*() { + const projectRoot = yield* resolveProjectRoot() + + yield* ensureCleanDirectories(projectRoot) + + const env = yield* Effect.promise(() => + new DockerComposeEnvironment(projectRoot, "docker-compose.yml") + .withProjectName("amp-integration-tests") + .withWaitStrategy("postgres-1", Wait.forHealthCheck()) + .withWaitStrategy("amp-1", Wait.forLogMessage(/Admin API running at/)) + .withStartupTimeout(120_000) + .up(["postgres", "anvil", "amp"]) + ) + + return env + }), + (environment) => Effect.promise(() => environment.down({ removeVolumes: true })) + ) +).pipe(Layer.provide(NodeContext.layer)) + +/** + * AdminApi layer — HTTP client talking to real Amp admin API. + * No auth layer — Amp runs in dev mode. + */ +const AdminApiLayer = AdminService.layer({ url: AMP_ADMIN_URL }).pipe( + Layer.provide(NodeHttpClient.layerUndici) +) + +/** + * ArrowFlight layer — gRPC client talking to real Amp Arrow Flight server. + * No auth layer — Amp runs in dev mode. + */ +const ArrowFlightLayer = ArrowFlight.layer.pipe( + Layer.provide(ArrowFlightNode.layerTransportGrpc({ baseUrl: AMP_FLIGHT_URL })) +) + +export const IntegrationLayer = Layer.mergeAll(AdminApiLayer, ArrowFlightLayer).pipe( + Layer.provideMerge(DockerComposeLayer) +) diff --git a/packages/amp/vitest.config.ts b/packages/amp/vitest.config.ts index fb966ae..db2fb07 100644 --- a/packages/amp/vitest.config.ts +++ b/packages/amp/vitest.config.ts @@ -1,6 +1,10 @@ import { mergeConfig, type ViteUserConfig } from "vitest/config" import shared from "../../vitest.shared.ts" -const config: ViteUserConfig = {} +const config: ViteUserConfig = { + test: { + exclude: ["test/integration/**"] + } +} export default mergeConfig(shared, config) diff --git a/packages/amp/vitest.integration.config.ts b/packages/amp/vitest.integration.config.ts new file mode 100644 index 0000000..a689dd4 --- /dev/null +++ b/packages/amp/vitest.integration.config.ts @@ -0,0 +1,15 @@ +import { mergeConfig, type ViteUserConfig } from "vitest/config" +import shared from "../../vitest.shared.ts" + +const config: ViteUserConfig = { + test: { + include: ["test/integration/**/*.test.ts"], + testTimeout: 60_000, + hookTimeout: 180_000, + sequence: { + concurrent: false + } + } +} + +export default mergeConfig(shared, config) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b139e2a..4ad246e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -74,6 +74,9 @@ importers: rulesync: specifier: ^6.7.0 version: 6.7.0(valibot@1.2.0(typescript@5.9.3)) + testcontainers: + specifier: ^11.12.0 + version: 11.12.0 ts-patch: specifier: ^3.3.0 version: 3.3.0 @@ -259,6 +262,9 @@ packages: resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} engines: {node: '>=6.9.0'} + '@balena/dockerignore@1.0.2': + resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==} + '@bcoe/v8-coverage@1.0.2': resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} @@ -657,6 +663,20 @@ packages: cpu: [x64] os: [win32] + '@grpc/grpc-js@1.14.3': + resolution: {integrity: sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==} + engines: {node: '>=12.10.0'} + + '@grpc/proto-loader@0.7.15': + resolution: {integrity: sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==} + engines: {node: '>=6'} + hasBin: true + + '@grpc/proto-loader@0.8.0': + resolution: {integrity: sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==} + engines: {node: '>=6'} + hasBin: true + '@hono/node-server@1.19.9': resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==} engines: {node: '>=18.14.1'} @@ -671,6 +691,10 @@ packages: resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} engines: {node: 20 || >=22} + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -687,6 +711,12 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@js-sdsl/ordered-map@4.4.2': + resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} + + '@kwsites/file-exists@1.1.1': + resolution: {integrity: sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==} + '@modelcontextprotocol/sdk@1.26.0': resolution: {integrity: sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==} engines: {node: '>=18'} @@ -928,9 +958,43 @@ packages: resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==} engines: {node: '>= 10.0.0'} + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@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.56.0': resolution: {integrity: sha512-LNKIPA5k8PF1+jAFomGe3qN3bbIgJe/IlpDBwuVjrDKrJhVWywgnJvflMt/zkbVNLFtF1+94SljYQS6e99klnw==} cpu: [arm] @@ -1113,6 +1177,12 @@ packages: '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/docker-modem@3.0.6': + resolution: {integrity: sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==} + + '@types/dockerode@4.0.1': + resolution: {integrity: sha512-cmUpB+dPN955PxBEuXE3f6lKO1hHiIGYJA46IVF3BJpNsZGvtBDcRnlrHYHtOH/B6vtDOyl2kZ2ShAu3mgc27Q==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -1128,6 +1198,9 @@ packages: '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + '@types/node@18.19.130': + resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} + '@types/node@25.1.0': resolution: {integrity: sha512-t7frlewr6+cbx+9Ohpl0NOTKXZNV9xHRmNOvql47BFJKcEG1CxtxlPEEe+gR9uhVWM4DwhnvTF110mIL4yP9RA==} @@ -1149,6 +1222,15 @@ packages: '@types/serve-static@1.15.10': resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} + '@types/ssh2-streams@0.1.13': + resolution: {integrity: sha512-faHyY3brO9oLEA0QlcO8N2wT7R0+1sHWZvQ+y3rMLwdY1ZyS1z0W3t65j9PqT4HmQ6ALzNe7RZlNuCNE0wBSWA==} + + '@types/ssh2@0.5.52': + resolution: {integrity: sha512-lbLLlXxdCZOSJMCInKH2+9V/77ET2J6NPQHpFI0kda61Dd1KglJs+fPQBchizmzYSOJBgdTajhPqBO1xxLywvg==} + + '@types/ssh2@1.15.5': + resolution: {integrity: sha512-N1ASjp/nXH3ovBHddRJpli4ozpk6UdDYIX4RJWFa9L1YKnzdhTlVmiGHm4DZnj/jLbqZpes4aeR30EFGQtvhQQ==} + '@typescript-eslint/project-service@8.50.0': resolution: {integrity: sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1293,6 +1375,10 @@ packages: zod: optional: true + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} @@ -1338,12 +1424,23 @@ packages: app-module-path@2.2.0: resolution: {integrity: sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ==} + 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'} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + asn1@0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -1355,12 +1452,26 @@ packages: ast-v8-to-istanbul@0.3.10: resolution: {integrity: sha512-p4K7vMz2ZSk3wN8l5o3y2bJAoZXT3VuJI5OLTATY/01CYWumWvwkUw0SqDBnNq6IiTO3qDa1eSQDibAV8g7XOQ==} + async-lock@1.4.1: + resolution: {integrity: sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} axios@1.13.4: resolution: {integrity: sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==} + b4a@1.8.0: + resolution: {integrity: sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==} + peerDependencies: + react-native-b4a: '*' + peerDependenciesMeta: + react-native-b4a: + optional: true + babel-plugin-annotate-pure-calls@0.5.0: resolution: {integrity: sha512-bWlaZl2qsJKHv9BJgF1g6bQ04wK/7Topq9g59I795W9jpx9lNs9N5LK5NjlEBCDhHncrO0vcoAMuHJR3oWnTeQ==} engines: {node: '>=18'} @@ -1370,6 +1481,44 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + bare-events@2.8.2: + resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==} + peerDependencies: + bare-abort-controller: '*' + peerDependenciesMeta: + bare-abort-controller: + optional: true + + bare-fs@4.5.4: + resolution: {integrity: sha512-POK4oplfA7P7gqvetNmCs4CNtm9fNsx+IAh7jH7GgU0OJdge2rso0R20TNWVq6VoWcCvsTdlNDaleLHGaKx8CA==} + engines: {bare: '>=1.16.0'} + peerDependencies: + bare-buffer: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + + bare-os@3.6.2: + resolution: {integrity: sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==} + engines: {bare: '>=1.14.0'} + + bare-path@3.0.0: + resolution: {integrity: sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==} + + bare-stream@2.8.0: + resolution: {integrity: sha512-reUN0M2sHRqCdG4lUK3Fw8w98eeUIZHL5c3H7Mbhk2yVBL+oofgaIp0ieLfD5QXwPCypBpmEEKU2WZKzbAk8GA==} + peerDependencies: + bare-buffer: '*' + bare-events: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + bare-events: + optional: true + + bare-url@2.3.2: + resolution: {integrity: sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -1377,6 +1526,9 @@ packages: resolution: {integrity: sha512-agD0MgJFUP/4nvjqzIB29zRPUuCF7Ge6mEv9s8dHrtYD7QWXRcx75rOADE/d5ah1NI+0vkDl0yorDd5U852IQQ==} hasBin: true + bcrypt-pbkdf@1.0.2: + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + before-after-hook@4.0.0: resolution: {integrity: sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==} @@ -1406,13 +1558,28 @@ 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@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + buildcheck@0.0.7: + resolution: {integrity: sha512-lHblz4ahamxpTmnsk+MNTRWsjYKv965MwOrSJyeD588rR3Jcu7swE+0wN5F+PbL5cjgu/9ObkhfzEPuofEMwLA==} + engines: {node: '>=10.0.0'} + bundle-name@4.1.0: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} + byline@5.0.0: + resolution: {integrity: sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==} + engines: {node: '>=0.10.0'} + bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -1440,6 +1607,9 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} @@ -1448,6 +1618,10 @@ packages: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + cliui@9.0.1: resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} engines: {node: '>=20'} @@ -1486,6 +1660,10 @@ packages: commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + compress-commons@6.0.2: + resolution: {integrity: sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==} + engines: {node: '>= 14'} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -1520,10 +1698,26 @@ packages: resolution: {integrity: sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==} engines: {node: '>= 0.8'} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cors@2.8.6: resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} engines: {node: '>= 0.10'} + 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@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -1630,6 +1824,18 @@ packages: peerDependencies: typescript: ^5.9.3 + docker-compose@1.3.1: + resolution: {integrity: sha512-rF0wH69G3CCcmkN9J1RVMQBaKe8o77LT/3XmqcLIltWWVxcWAzp2TnO7wS3n/umZHN3/EVrlT3exSBMal+Ou1w==} + engines: {node: '>= 6.0.0'} + + docker-modem@5.0.6: + resolution: {integrity: sha512-ens7BiayssQz/uAxGzH8zGXCtiV24rRWXdjNha5V4zSOcxmAZsfGVm/PPFbwQdqEkDnhG+SyR9E3zSHUbOKXBQ==} + engines: {node: '>= 8.0'} + + dockerode@4.0.9: + resolution: {integrity: sha512-iND4mcOWhPaCNh54WmK/KoSb35AFqPAUWFMffTQcp52uQt36b5uNwEJTSXntJZBbeGad72Crbi/hvDIv6us/6Q==} + engines: {node: '>= 8.0'} + dprint@0.51.1: resolution: {integrity: sha512-CEx+wYARxLAe9o7RCZ77GKae6DF7qjn5Rd98xbWdA3hB4PFBr+kHwLANmNHscNumBAIrCg5ZJj/Kz+OYbJ+GBA==} hasBin: true @@ -1638,6 +1844,9 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} @@ -1653,6 +1862,12 @@ packages: emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + encodeurl@2.0.0: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} @@ -1734,9 +1949,20 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + events-universal@1.0.1: + resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + eventsource-parser@3.0.6: resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} engines: {node: '>=18.0.0'} @@ -1777,6 +2003,9 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + fast-glob@3.3.3: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} @@ -1844,6 +2073,10 @@ packages: debug: optional: true + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + form-data@4.0.5: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} @@ -1860,6 +2093,9 @@ packages: resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} engines: {node: '>= 0.8'} + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fs-readdir-recursive@1.1.0: resolution: {integrity: sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==} @@ -1901,6 +2137,10 @@ packages: get-own-enumerable-property-symbols@3.0.2: resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} + get-port@7.1.0: + resolution: {integrity: sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==} + engines: {node: '>=16'} + get-proto@1.0.1: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} @@ -1913,6 +2153,11 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + glob@13.0.0: resolution: {integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==} engines: {node: 20 || >=22} @@ -2048,6 +2293,10 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -2088,6 +2337,10 @@ packages: resolution: {integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==} engines: {node: '>=0.10.0'} + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + is-stream@4.0.1: resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} engines: {node: '>=18'} @@ -2111,6 +2364,9 @@ packages: resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} engines: {node: '>=16'} + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -2135,6 +2391,9 @@ packages: resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} engines: {node: '>=8'} + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jiti@2.6.1: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true @@ -2201,10 +2460,26 @@ packages: kubernetes-types@1.30.0: resolution: {integrity: sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q==} + lazystream@1.0.1: + resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} + engines: {node: '>= 0.6.3'} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash@4.17.23: + resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} + log-symbols@4.1.0: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.2.4: resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} engines: {node: 20 || >=22} @@ -2292,6 +2567,10 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@5.1.7: + resolution: {integrity: sha512-FjiwU9HaHW6YB3H4a1sFudnv93lvydNjz2lmyUXR6IwKhGI+bgL3SOZrBGn6kvvX2pJvhEkGSGjyTHN47O4rqA==} + engines: {node: '>=10'} + minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -2303,6 +2582,14 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + module-definition@6.0.1: resolution: {integrity: sha512-FeVc50FTfVVQnolk/WQT8MX+2WVcDnTGiq6Wo+/+lJ2ET1bRVi3HG3YlJUfqagNMc/kUlFSoR96AJkxGpKz13g==} engines: {node: '>=18'} @@ -2330,6 +2617,9 @@ packages: multipasta@0.2.7: resolution: {integrity: sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA==} + nan@2.25.0: + resolution: {integrity: sha512-0M90Ag7Xn5KMLLZ7zliPWP3rT90P6PN+IzVFS0VqmnPktBk3700xUVv8Ikm9EUaUE5SDWdp/BIxdENzVznpm1g==} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2413,6 +2703,9 @@ packages: oxlint-tsgolint: optional: true + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + parse-ms@2.1.0: resolution: {integrity: sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==} engines: {node: '>=6'} @@ -2440,6 +2733,10 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + path-scurry@2.0.1: resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} engines: {node: 20 || >=22} @@ -2505,6 +2802,24 @@ packages: resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} engines: {node: '>=18'} + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + proper-lockfile@4.1.2: + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + + properties-reader@3.0.1: + resolution: {integrity: sha512-WPn+h9RGEExOKdu4bsF4HksG/uzd3cFq3MFtq8PsFeExPse5Ha/VOjQNyHhjboBFwGXGev6muJYTSPAOkROq2g==} + engines: {node: '>=18'} + + protobufjs@7.5.4: + resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==} + engines: {node: '>=12.0.0'} + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -2544,14 +2859,28 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true + 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'} + readable-stream@4.7.0: + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} + 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'} + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} @@ -2578,6 +2907,10 @@ packages: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -2603,6 +2936,9 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -2700,9 +3036,19 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + split-ca@1.0.1: + resolution: {integrity: sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==} + sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + ssh-remote-port-forward@1.0.4: + resolution: {integrity: sha512-x0LV1eVDwjf1gmG7TTnfqIzf+3VPRz7vrNIjX6oYLbeCrf/PeVY6hkT68Mg+q02qXxQhrLjB0jfgvhevoCRmLQ==} + + ssh2@1.17.0: + resolution: {integrity: sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ==} + engines: {node: '>=10.16.0'} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -2720,13 +3066,27 @@ packages: stream-to-array@2.3.0: resolution: {integrity: sha512-UsZtOYEn4tWU2RGLOXr/o/xjRBftZRlG3dEWoaHr8j4GuypJ3isitGbVyjQKAuMu+xbiop8q224TjiZWc4XTZA==} + streamx@2.23.0: + resolution: {integrity: sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==} + strict-event-emitter-types@2.0.0: resolution: {integrity: sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==} + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + string-width@7.2.0: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} + 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==} @@ -2787,6 +3147,28 @@ packages: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} + tar-fs@2.1.4: + resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==} + + tar-fs@3.1.1: + resolution: {integrity: sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + tar-stream@3.1.7: + resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} + + teex@1.0.1: + resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==} + + testcontainers@11.12.0: + resolution: {integrity: sha512-VWtH+UQejVYYvb53ohEZRbx2naxyDvwO9lQ6A0VgmVE2Oh8r9EF09I+BfmrXpd9N9ntpzhao9di2yNwibSz5KA==} + + text-decoder@1.2.7: + resolution: {integrity: sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -2806,6 +3188,10 @@ packages: resolution: {integrity: sha512-EORDwFMSZKrHPUVDhejCMDeAovRS5d8jZKiqALFiPp3cjKjEldPkxBY39ZSx3c45awz3RpKwJD1cCgGxEfy8/A==} engines: {node: '>= 20'} + tmp@0.2.5: + resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} + engines: {node: '>=14.14'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -2857,6 +3243,9 @@ packages: resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} engines: {node: '>=0.6.x'} + tweetnacl@0.14.5: + resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} + type-is@2.0.1: resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} engines: {node: '>= 0.6'} @@ -2870,6 +3259,9 @@ packages: resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} engines: {node: '>=18'} + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} @@ -2877,6 +3269,10 @@ packages: resolution: {integrity: sha512-Heho1hJD81YChi+uS2RkSjcVO+EQLmLSyUlHyp7Y/wFbxQaGb4WXVKD073JytrjXJVkSZVzoE2MCSOKugFGtOQ==} engines: {node: '>=20.18.1'} + undici@7.22.0: + resolution: {integrity: sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==} + engines: {node: '>=20.18.1'} + unicorn-magic@0.3.0: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} engines: {node: '>=18'} @@ -2904,6 +3300,10 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + uuid@11.1.0: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true @@ -3032,6 +3432,14 @@ packages: engines: {node: '>=8'} hasBin: true + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + wrap-ansi@9.0.2: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} @@ -3102,10 +3510,18 @@ packages: engines: {node: '>= 14.6'} hasBin: true + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + yargs-parser@22.0.0: resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + yargs@18.0.0: resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} @@ -3114,6 +3530,10 @@ packages: resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} engines: {node: '>=18'} + zip-stream@6.0.1: + resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} + engines: {node: '>= 14'} + zod-to-json-schema@3.25.1: resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==} peerDependencies: @@ -3255,6 +3675,8 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@balena/dockerignore@1.0.2': {} + '@bcoe/v8-coverage@1.0.2': {} '@borewit/text-codec@0.2.1': {} @@ -3536,6 +3958,25 @@ snapshots: '@esbuild/win32-x64@0.27.2': optional: true + '@grpc/grpc-js@1.14.3': + dependencies: + '@grpc/proto-loader': 0.8.0 + '@js-sdsl/ordered-map': 4.4.2 + + '@grpc/proto-loader@0.7.15': + dependencies: + lodash.camelcase: 4.3.0 + long: 5.3.2 + protobufjs: 7.5.4 + yargs: 17.7.2 + + '@grpc/proto-loader@0.8.0': + dependencies: + lodash.camelcase: 4.3.0 + long: 5.3.2 + protobufjs: 7.5.4 + yargs: 17.7.2 + '@hono/node-server@1.19.9(hono@4.11.8)': dependencies: hono: 4.11.8 @@ -3546,6 +3987,15 @@ snapshots: dependencies: '@isaacs/balanced-match': 4.0.1 + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.2 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -3565,6 +4015,14 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@js-sdsl/ordered-map@4.4.2': {} + + '@kwsites/file-exists@1.1.1': + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + '@modelcontextprotocol/sdk@1.26.0(zod@4.3.6)': dependencies: '@hono/node-server': 1.19.9(hono@4.11.8) @@ -3774,8 +4232,34 @@ snapshots: '@parcel/watcher-win32-ia32': 2.5.6 '@parcel/watcher-win32-x64': 2.5.6 + '@pkgjs/parseargs@0.11.0': + optional: true + '@polka/url@1.0.0-next.29': {} + '@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.56.0': optional: true @@ -3912,6 +4396,17 @@ snapshots: '@types/deep-eql@4.0.2': {} + '@types/docker-modem@3.0.6': + dependencies: + '@types/node': 25.2.3 + '@types/ssh2': 1.15.5 + + '@types/dockerode@4.0.1': + dependencies: + '@types/docker-modem': 3.0.6 + '@types/node': 25.2.3 + '@types/ssh2': 1.15.5 + '@types/estree@1.0.8': {} '@types/express-serve-static-core@4.19.7': @@ -3932,6 +4427,10 @@ snapshots: '@types/mime@1.3.5': {} + '@types/node@18.19.130': + dependencies: + undici-types: 5.26.5 + '@types/node@25.1.0': dependencies: undici-types: 7.16.0 @@ -3959,6 +4458,19 @@ snapshots: '@types/node': 25.2.3 '@types/send': 0.17.6 + '@types/ssh2-streams@0.1.13': + dependencies: + '@types/node': 25.2.3 + + '@types/ssh2@0.5.52': + dependencies: + '@types/node': 25.2.3 + '@types/ssh2-streams': 0.1.13 + + '@types/ssh2@1.15.5': + dependencies: + '@types/node': 18.19.130 + '@typescript-eslint/project-service@8.50.0(typescript@5.9.3)': dependencies: '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3) @@ -4137,6 +4649,10 @@ snapshots: typescript: 5.9.3 zod: 4.3.6 + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + accepts@1.3.8: dependencies: mime-types: 2.1.35 @@ -4178,12 +4694,39 @@ snapshots: app-module-path@2.2.0: {} + archiver-utils@5.0.2: + dependencies: + glob: 10.5.0 + graceful-fs: 4.2.11 + is-stream: 2.0.1 + lazystream: 1.0.1 + lodash: 4.17.23 + normalize-path: 3.0.0 + readable-stream: 4.7.0 + + archiver@7.0.1: + dependencies: + archiver-utils: 5.0.2 + async: 3.2.6 + buffer-crc32: 1.0.0 + readable-stream: 4.7.0 + readdir-glob: 1.1.3 + tar-stream: 3.1.7 + zip-stream: 6.0.1 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 argparse@2.0.1: {} + asn1@0.2.6: + dependencies: + safer-buffer: 2.1.2 + assertion-error@2.0.1: {} ast-module-types@6.0.1: {} @@ -4194,6 +4737,10 @@ snapshots: estree-walker: 3.0.3 js-tokens: 9.0.1 + async-lock@1.4.1: {} + + async@3.2.6: {} + asynckit@0.4.0: {} axios@1.13.4(debug@4.4.3): @@ -4204,16 +4751,60 @@ snapshots: transitivePeerDependencies: - debug + b4a@1.8.0: {} + babel-plugin-annotate-pure-calls@0.5.0(@babel/core@7.28.6): dependencies: '@babel/core': 7.28.6 balanced-match@1.0.2: {} + bare-events@2.8.2: {} + + bare-fs@4.5.4: + dependencies: + bare-events: 2.8.2 + bare-path: 3.0.0 + bare-stream: 2.8.0(bare-events@2.8.2) + bare-url: 2.3.2 + fast-fifo: 1.3.2 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + optional: true + + bare-os@3.6.2: + optional: true + + bare-path@3.0.0: + dependencies: + bare-os: 3.6.2 + optional: true + + bare-stream@2.8.0(bare-events@2.8.2): + dependencies: + streamx: 2.23.0 + teex: 1.0.1 + optionalDependencies: + bare-events: 2.8.2 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + optional: true + + bare-url@2.3.2: + dependencies: + bare-path: 3.0.0 + optional: true + base64-js@1.5.1: {} baseline-browser-mapping@2.9.17: {} + bcrypt-pbkdf@1.0.2: + dependencies: + tweetnacl: 0.14.5 + before-after-hook@4.0.0: {} binary-extensions@2.3.0: @@ -4260,15 +4851,27 @@ snapshots: node-releases: 2.0.27 update-browserslist-db: 1.2.3(browserslist@4.28.1) + buffer-crc32@1.0.0: {} + buffer@5.7.1: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + buildcheck@0.0.7: + optional: true + bundle-name@4.1.0: dependencies: run-applescript: 7.1.0 + byline@5.0.0: {} + bytes@3.1.2: {} call-bind-apply-helpers@1.0.2: @@ -4303,12 +4906,20 @@ snapshots: fsevents: 2.3.3 optional: true + chownr@1.1.4: {} + cli-cursor@3.1.0: dependencies: restore-cursor: 3.1.0 cli-spinners@2.9.2: {} + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + cliui@9.0.1: dependencies: string-width: 7.2.0 @@ -4337,6 +4948,14 @@ snapshots: commondir@1.0.1: {} + 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.7.0 + concat-map@0.0.1: {} consola@3.4.2: {} @@ -4360,11 +4979,26 @@ snapshots: depd: 2.0.0 keygrip: 1.1.0 + core-util-is@1.0.3: {} + cors@2.8.6: dependencies: object-assign: 4.1.1 vary: 1.1.2 + cpu-features@0.0.10: + dependencies: + buildcheck: 0.0.7 + nan: 2.25.0 + optional: true + + crc-32@1.2.2: {} + + crc32-stream@6.0.0: + dependencies: + crc-32: 1.2.2 + readable-stream: 4.7.0 + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -4469,6 +5103,31 @@ snapshots: transitivePeerDependencies: - supports-color + docker-compose@1.3.1: + dependencies: + yaml: 2.8.2 + + docker-modem@5.0.6: + dependencies: + debug: 4.4.3 + readable-stream: 3.6.2 + split-ca: 1.0.1 + ssh2: 1.17.0 + transitivePeerDependencies: + - supports-color + + dockerode@4.0.9: + dependencies: + '@balena/dockerignore': 1.0.2 + '@grpc/grpc-js': 1.14.3 + '@grpc/proto-loader': 0.7.15 + docker-modem: 5.0.6 + protobufjs: 7.5.4 + tar-fs: 2.1.4 + uuid: 10.0.0 + transitivePeerDependencies: + - supports-color + dprint@0.51.1: optionalDependencies: '@dprint/darwin-arm64': 0.51.1 @@ -4489,6 +5148,8 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + eastasianwidth@0.2.0: {} + ee-first@1.1.1: {} effect@3.19.16: @@ -4505,6 +5166,10 @@ snapshots: emoji-regex@10.6.0: {} + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + encodeurl@2.0.0: {} end-of-stream@1.4.5: @@ -4594,8 +5259,18 @@ snapshots: etag@1.8.1: {} + event-target-shim@5.0.1: {} + eventemitter3@5.0.1: {} + events-universal@1.0.1: + dependencies: + bare-events: 2.8.2 + transitivePeerDependencies: + - bare-abort-controller + + events@3.3.0: {} + eventsource-parser@3.0.6: {} eventsource@3.0.7: @@ -4669,6 +5344,8 @@ snapshots: fast-deep-equal@3.1.3: {} + fast-fifo@1.3.2: {} + fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -4763,6 +5440,11 @@ snapshots: optionalDependencies: debug: 4.4.3 + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + form-data@4.0.5: dependencies: asynckit: 0.4.0 @@ -4777,6 +5459,8 @@ snapshots: fresh@2.0.0: {} + fs-constants@1.0.0: {} + fs-readdir-recursive@1.1.0: {} fs.realpath@1.0.0: {} @@ -4814,6 +5498,8 @@ snapshots: get-own-enumerable-property-symbols@3.0.2: {} + get-port@7.1.0: {} + get-proto@1.0.1: dependencies: dunder-proto: 1.0.1 @@ -4828,6 +5514,15 @@ snapshots: dependencies: is-glob: 4.0.3 + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + glob@13.0.0: dependencies: minimatch: 10.1.1 @@ -4958,6 +5653,8 @@ snapshots: is-extglob@2.1.1: {} + is-fullwidth-code-point@3.0.0: {} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -4982,6 +5679,8 @@ snapshots: is-regexp@1.0.0: {} + is-stream@2.0.1: {} + is-stream@4.0.1: {} is-unicode-supported@0.1.0: {} @@ -4996,6 +5695,8 @@ snapshots: dependencies: is-inside-container: 1.0.0 + isarray@1.0.0: {} + isexe@2.0.0: {} isexe@3.1.1: {} @@ -5017,6 +5718,12 @@ snapshots: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + jiti@2.6.1: {} jose@6.1.3: {} @@ -5086,11 +5793,23 @@ snapshots: kubernetes-types@1.30.0: {} + lazystream@1.0.1: + dependencies: + readable-stream: 2.3.8 + + lodash.camelcase@4.3.0: {} + + lodash@4.17.23: {} + log-symbols@4.1.0: dependencies: chalk: 4.1.2 is-unicode-supported: 0.1.0 + long@5.3.2: {} + + lru-cache@10.4.3: {} + lru-cache@11.2.4: {} lru-cache@5.1.1: @@ -5178,6 +5897,10 @@ snapshots: dependencies: brace-expansion: 1.1.12 + minimatch@5.1.7: + dependencies: + brace-expansion: 2.0.2 + minimatch@9.0.5: dependencies: brace-expansion: 2.0.2 @@ -5186,6 +5909,10 @@ snapshots: minipass@7.1.2: {} + mkdirp-classic@0.5.3: {} + + mkdirp@3.0.1: {} + module-definition@6.0.1: dependencies: ast-module-types: 6.0.1 @@ -5220,6 +5947,9 @@ snapshots: multipasta@0.2.7: {} + nan@2.25.0: + optional: true + nanoid@3.3.11: {} negotiator@0.6.3: {} @@ -5239,8 +5969,7 @@ snapshots: dependencies: '@babel/parser': 7.28.6 - normalize-path@3.0.0: - optional: true + normalize-path@3.0.0: {} npm-run-path@6.0.0: dependencies: @@ -5312,6 +6041,8 @@ snapshots: '@oxlint/win32-arm64': 1.42.0 '@oxlint/win32-x64': 1.42.0 + package-json-from-dist@1.0.1: {} + parse-ms@2.1.0: {} parse-ms@4.0.0: {} @@ -5326,6 +6057,11 @@ snapshots: path-parse@1.0.7: {} + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + path-scurry@2.0.1: dependencies: lru-cache: 11.2.4 @@ -5403,6 +6139,38 @@ snapshots: dependencies: parse-ms: 4.0.0 + process-nextick-args@2.0.1: {} + + process@0.11.10: {} + + proper-lockfile@4.1.2: + dependencies: + graceful-fs: 4.2.11 + retry: 0.12.0 + signal-exit: 3.0.7 + + properties-reader@3.0.1: + dependencies: + '@kwsites/file-exists': 1.1.1 + mkdirp: 3.0.1 + transitivePeerDependencies: + - supports-color + + protobufjs@7.5.4: + 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': 25.2.3 + long: 5.3.2 + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 @@ -5443,17 +6211,41 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 + 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 string_decoder: 1.3.0 util-deprecate: 1.0.2 + readable-stream@4.7.0: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + + readdir-glob@1.1.3: + dependencies: + minimatch: 5.1.7 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 optional: true + require-directory@2.1.1: {} + require-from-string@2.0.2: {} requirejs-config-file@4.0.0: @@ -5476,6 +6268,8 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 + retry@0.12.0: {} + reusify@1.1.0: {} rollup@4.56.0: @@ -5552,6 +6346,8 @@ snapshots: dependencies: queue-microtask: 1.2.3 + safe-buffer@5.1.2: {} + safe-buffer@5.2.1: {} safer-buffer@2.1.2: {} @@ -5656,8 +6452,23 @@ snapshots: source-map@0.6.1: optional: true + split-ca@1.0.1: {} + sprintf-js@1.0.3: {} + ssh-remote-port-forward@1.0.4: + dependencies: + '@types/ssh2': 0.5.52 + ssh2: 1.17.0 + + ssh2@1.17.0: + dependencies: + asn1: 0.2.6 + bcrypt-pbkdf: 1.0.2 + optionalDependencies: + cpu-features: 0.0.10 + nan: 2.25.0 + stackback@0.0.2: {} statuses@1.5.0: {} @@ -5670,14 +6481,39 @@ snapshots: dependencies: any-promise: 1.3.0 + streamx@2.23.0: + dependencies: + events-universal: 1.0.1 + fast-fifo: 1.3.2 + text-decoder: 1.2.7 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + strict-event-emitter-types@2.0.0: {} + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.2 + string-width@7.2.0: dependencies: emoji-regex: 10.6.0 get-east-asian-width: 1.4.0 strip-ansi: 7.1.2 + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 @@ -5722,6 +6558,79 @@ snapshots: tapable@2.3.0: {} + tar-fs@2.1.4: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.3 + tar-stream: 2.2.0 + + tar-fs@3.1.1: + dependencies: + pump: 3.0.3 + tar-stream: 3.1.7 + optionalDependencies: + bare-fs: 4.5.4 + bare-path: 3.0.0 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - react-native-b4a + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + tar-stream@3.1.7: + dependencies: + b4a: 1.8.0 + fast-fifo: 1.3.2 + streamx: 2.23.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + teex@1.0.1: + dependencies: + streamx: 2.23.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + optional: true + + testcontainers@11.12.0: + dependencies: + '@balena/dockerignore': 1.0.2 + '@types/dockerode': 4.0.1 + archiver: 7.0.1 + async-lock: 1.4.1 + byline: 5.0.0 + debug: 4.4.3 + docker-compose: 1.3.1 + dockerode: 4.0.9 + get-port: 7.1.0 + proper-lockfile: 4.1.2 + properties-reader: 3.0.1 + ssh-remote-port-forward: 1.0.4 + tar-fs: 3.1.1 + tmp: 0.2.5 + undici: 7.22.0 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - react-native-b4a + - supports-color + + text-decoder@1.2.7: + dependencies: + b4a: 1.8.0 + transitivePeerDependencies: + - react-native-b4a + tinybench@2.9.0: {} tinyexec@1.0.2: {} @@ -5737,6 +6646,8 @@ snapshots: dependencies: punycode: 2.3.1 + tmp@0.2.5: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -5785,6 +6696,8 @@ snapshots: tsscmp@1.0.6: {} + tweetnacl@0.14.5: {} + type-is@2.0.1: dependencies: content-type: 1.0.5 @@ -5795,10 +6708,14 @@ snapshots: uint8array-extras@1.5.0: {} + undici-types@5.26.5: {} + undici-types@7.16.0: {} undici@7.19.0: {} + undici@7.22.0: {} + unicorn-magic@0.3.0: {} unicorn-magic@0.4.0: {} @@ -5817,6 +6734,8 @@ snapshots: util-deprecate@1.0.2: {} + uuid@10.0.0: {} + uuid@11.1.0: {} valibot@1.2.0(typescript@5.9.3): @@ -5979,6 +6898,18 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.1.2 + wrap-ansi@9.0.2: dependencies: ansi-styles: 6.2.3 @@ -6010,8 +6941,20 @@ snapshots: yaml@2.8.2: {} + yargs-parser@21.1.1: {} + yargs-parser@22.0.0: {} + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yargs@18.0.0: dependencies: cliui: 9.0.1 @@ -6023,6 +6966,12 @@ snapshots: yoctocolors@2.1.2: {} + zip-stream@6.0.1: + dependencies: + archiver-utils: 5.0.2 + compress-commons: 6.0.2 + readable-stream: 4.7.0 + zod-to-json-schema@3.25.1(zod@4.3.6): dependencies: zod: 4.3.6