From c8f3e662dc131882a283a8fc4510ab7a64876410 Mon Sep 17 00:00:00 2001 From: Nathan Flurry Date: Mon, 9 Jun 2025 21:48:46 +0000 Subject: [PATCH] feat(toolchain): remote build method --- Cargo.lock | 1 + cloud/packages/ci-manager/Dockerfile | 25 + cloud/packages/ci-manager/package.json | 32 + cloud/packages/ci-manager/src/build-store.ts | 146 + .../ci-manager/src/executors/docker.ts | 94 + .../ci-manager/src/executors/rivet.ts | 172 ++ cloud/packages/ci-manager/src/index.ts | 4 + .../packages/ci-manager/src/kaniko-runner.ts | 58 + .../packages/ci-manager/src/oci-converter.ts | 83 + .../packages/ci-manager/src/rivet-uploader.ts | 235 ++ cloud/packages/ci-manager/src/server.ts | 321 +++ cloud/packages/ci-manager/src/types.ts | 43 + .../ci-manager/tests/docker-e2e.test.ts | 227 ++ .../ci-manager/tests/oci-converter.test.ts | 203 ++ .../ci-manager/tests/rivet-e2e.test.ts | 243 ++ cloud/packages/ci-manager/tests/test-utils.ts | 358 +++ .../ci-manager/tests/upload-workflow.test.ts | 167 ++ cloud/packages/ci-manager/tsconfig.json | 43 + cloud/packages/ci-manager/yarn.lock | 2351 +++++++++++++++++ cloud/packages/ci-runner/Dockerfile | 9 + cloud/rivet.json | 15 + examples/system-test-actor/rivet.jsonc | 5 +- package.json | 14 +- packages/toolchain/cli/src/main.rs | 4 +- packages/toolchain/toolchain/Cargo.toml | 1 + .../toolchain/src/config/build/docker.rs | 3 + .../src/tasks/build_publish/docker.rs | 72 +- .../toolchain/src/util/docker/build.rs | 211 +- .../toolchain/src/util/docker/build_remote.rs | 611 +++++ .../toolchain/src/util/docker/mod.rs | 1 + scripts/cloud/upload-builds.ts | 83 + yarn.lock | 1143 +++++++- 32 files changed, 6792 insertions(+), 186 deletions(-) create mode 100644 cloud/packages/ci-manager/Dockerfile create mode 100644 cloud/packages/ci-manager/package.json create mode 100644 cloud/packages/ci-manager/src/build-store.ts create mode 100644 cloud/packages/ci-manager/src/executors/docker.ts create mode 100644 cloud/packages/ci-manager/src/executors/rivet.ts create mode 100644 cloud/packages/ci-manager/src/index.ts create mode 100644 cloud/packages/ci-manager/src/kaniko-runner.ts create mode 100644 cloud/packages/ci-manager/src/oci-converter.ts create mode 100644 cloud/packages/ci-manager/src/rivet-uploader.ts create mode 100644 cloud/packages/ci-manager/src/server.ts create mode 100644 cloud/packages/ci-manager/src/types.ts create mode 100644 cloud/packages/ci-manager/tests/docker-e2e.test.ts create mode 100644 cloud/packages/ci-manager/tests/oci-converter.test.ts create mode 100644 cloud/packages/ci-manager/tests/rivet-e2e.test.ts create mode 100644 cloud/packages/ci-manager/tests/test-utils.ts create mode 100644 cloud/packages/ci-manager/tests/upload-workflow.test.ts create mode 100644 cloud/packages/ci-manager/tsconfig.json create mode 100644 cloud/packages/ci-manager/yarn.lock create mode 100644 cloud/packages/ci-runner/Dockerfile create mode 100644 cloud/rivet.json create mode 100644 packages/toolchain/toolchain/src/util/docker/build_remote.rs create mode 100755 scripts/cloud/upload-builds.ts diff --git a/Cargo.lock b/Cargo.lock index 34eba352a4..49bf99e734 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12984,6 +12984,7 @@ dependencies = [ "const_format", "deno-embed", "dirs", + "flate2", "futures-util", "humansize", "ignore", diff --git a/cloud/packages/ci-manager/Dockerfile b/cloud/packages/ci-manager/Dockerfile new file mode 100644 index 0000000000..631e6830ab --- /dev/null +++ b/cloud/packages/ci-manager/Dockerfile @@ -0,0 +1,25 @@ +# Build stage - includes dev dependencies +FROM node:22-alpine AS builder +ENV NODE_ENV=development + +WORKDIR /app +RUN npm i -g corepack && corepack enable +COPY package.json yarn.lock ./ +RUN yarn install --immutable +COPY . . +RUN yarn build + +# Production stage - only prod dependencies +FROM node:22-alpine AS release +ENV NODE_ENV=production + +RUN adduser -s /bin/sh -D rivet +WORKDIR /app +RUN apk add --no-cache skopeo umoci && npm i -g corepack && corepack enable +COPY package.json yarn.lock ./ +RUN yarn config set nodeLinker node-modules && yarn install --immutable +COPY --from=builder /app/dist ./dist +RUN chown -R rivet:rivet /app +USER rivet +EXPOSE 3000 +CMD ["node", "dist/index.js"] diff --git a/cloud/packages/ci-manager/package.json b/cloud/packages/ci-manager/package.json new file mode 100644 index 0000000000..22780507ec --- /dev/null +++ b/cloud/packages/ci-manager/package.json @@ -0,0 +1,32 @@ +{ + "name": "ci-manager", + "private": true, + "peerDependencies": { + "typescript": "^5" + }, + "scripts": { + "prepare-builds": "tsx scripts/prepare-builds.ts", + "check-types": "tsc --noEmit", + "test": "vitest", + "build": "tsc" + }, + "dependencies": { + "@rivet-gg/api": "^25.4.2", + "hono": "^4.7.11", + "nanoevents": "^9.1.0", + "zod": "^3.25.56" + }, + "devDependencies": { + "@hono/node-server": "^1.14.4", + "@types/eventsource": "^1.1.15", + "@types/node": "^22.15.30", + "eventsource": "^4.0.0", + "get-port": "^7.1.0", + "tar": "^7.4.3", + "tsx": "^4.19.4", + "typescript": "^5.7.2", + "vitest": "^3.2.2", + "zx": "^8.1.9" + }, + "packageManager": "yarn@4.6.0" +} diff --git a/cloud/packages/ci-manager/src/build-store.ts b/cloud/packages/ci-manager/src/build-store.ts new file mode 100644 index 0000000000..2d5612010d --- /dev/null +++ b/cloud/packages/ci-manager/src/build-store.ts @@ -0,0 +1,146 @@ +import { BuildInfo, BuildEvent, Status } from "./types"; +import { randomUUID } from "crypto"; +import { mkdir, rm } from "fs/promises"; +import { join, dirname } from "path"; +import { createNanoEvents } from "nanoevents"; + +export class BuildStore { + private builds = new Map(); + private tempDir: string; + public emitter = createNanoEvents<{ + "build-event": (buildId: string, event: BuildEvent) => void; + "status-change": (buildId: string, status: Status) => void; + }>(); + + constructor(tempDir: string = "/tmp/ci-builds") { + this.tempDir = tempDir; + } + + async init() { + await mkdir(this.tempDir, { recursive: true }); + } + + createBuild(buildName: string, dockerfilePath: string, environmentId: string): string { + const id = randomUUID(); + const contextPath = join(this.tempDir, id, "context.tar.gz"); + const outputPath = join(this.tempDir, id, "output.tar.gz"); + + const build: BuildInfo = { + id, + status: { type: "starting", data: {} }, + buildName, + dockerfilePath, + environmentId, + contextPath, + outputPath, + events: [], + createdAt: new Date(), + }; + + // Set up 10-minute cleanup timeout + build.cleanupTimeout = setTimeout( + () => { + this.cleanupBuild(id, "timeout"); + }, + 10 * 60 * 1000, + ); // 10 minutes + + this.builds.set(id, build); + return id; + } + + getBuild(id: string): BuildInfo | undefined { + return this.builds.get(id); + } + + updateStatus(id: string, status: Status) { + const build = this.builds.get(id); + if ( + build && + build.status.type !== "success" && + build.status.type !== "failure" + ) { + build.status = status; + const event = { type: "status", data: status } as BuildEvent; + build.events.push(event); + this.emitter.emit("build-event", id, event); + this.emitter.emit("status-change", id, status); + console.log(`[${id}] status: ${JSON.stringify(status)}`); + } + } + + addLog(id: string, line: string) { + console.log(`[${id}] ${line}`); + const build = this.builds.get(id); + if (build) { + const event: BuildEvent = { type: "log", data: { line } }; + build.events.push(event); + this.emitter.emit("build-event", id, event); + } + } + + setContainerProcess(id: string, process: any) { + const build = this.builds.get(id); + if (build) { + build.containerProcess = process; + } + } + + getContextPath(id: string): string | undefined { + return this.builds.get(id)?.contextPath; + } + + getOutputPath(id: string): string | undefined { + return this.builds.get(id)?.outputPath; + } + + markDownloaded(id: string) { + const build = this.builds.get(id); + if (build) { + build.downloadedAt = new Date(); + // Trigger cleanup after download + setTimeout(() => { + this.cleanupBuild(id, "downloaded"); + }, 1000); // Small delay to ensure download is complete + } + } + + private async cleanupBuild(id: string, reason: "timeout" | "downloaded") { + const build = this.builds.get(id); + if (!build) return; + + console.log(`Cleaning up build ${id} (reason: ${reason})`); + + try { + // Clear the timeout if it exists + if (build.cleanupTimeout) { + clearTimeout(build.cleanupTimeout); + } + + // Remove build directory and all files + if (build.contextPath) { + const buildDir = dirname(build.contextPath); + try { + await rm(buildDir, { recursive: true, force: true }); + console.log(`Removed build directory: ${buildDir}`); + } catch (error) { + console.warn( + `Failed to remove build directory ${buildDir}:`, + error, + ); + } + } + + // Remove from memory + this.builds.delete(id); + console.log(`Build ${id} cleaned up successfully`); + } catch (error) { + console.error(`Error cleaning up build ${id}:`, error); + } + } + + // Manual cleanup method for testing or admin use + async manualCleanup(id: string) { + await this.cleanupBuild(id, "downloaded"); + } +} diff --git a/cloud/packages/ci-manager/src/executors/docker.ts b/cloud/packages/ci-manager/src/executors/docker.ts new file mode 100644 index 0000000000..0adceab46d --- /dev/null +++ b/cloud/packages/ci-manager/src/executors/docker.ts @@ -0,0 +1,94 @@ +import { spawn } from "node:child_process"; +import { BuildStore } from "../build-store"; + +export async function runDockerBuild( + buildStore: BuildStore, + serverUrl: string, + buildId: string, +): Promise { + const build = buildStore.getBuild(buildId); + if (!build) { + throw new Error(`Build ${buildId} not found`); + } + + const contextUrl = `${serverUrl}/builds/${buildId}/kaniko/context.tar.gz`; + const outputUrl = `${serverUrl}/builds/${buildId}/kaniko/output.tar.gz`; + + const kanikoArgs = [ + "run", + "--rm", + "--network=host", + "-e", + `CONTEXT_URL=${contextUrl}`, + "-e", + `OUTPUT_URL=${outputUrl}`, + "-e", + `DESTINATION=${buildId}:latest`, + "-e", + `DOCKERFILE_PATH=${build.dockerfilePath}`, + "ci-runner", + ]; + + buildStore.addLog( + buildId, + `Starting kaniko with args: docker ${kanikoArgs.join(" ")}`, + ); + + return new Promise((resolve, reject) => { + const dockerProcess = spawn("docker", kanikoArgs, { + stdio: ["pipe", "pipe", "pipe"], + }); + + buildStore.setContainerProcess(buildId, dockerProcess); + + dockerProcess.stdout?.on("data", (data) => { + const lines = data + .toString() + .split("\n") + .filter((line: string) => line.trim()); + lines.forEach((line: string) => { + buildStore.addLog(buildId, `[kaniko] ${line}`); + }); + }); + + dockerProcess.stderr?.on("data", (data) => { + const lines = data + .toString() + .split("\n") + .filter((line: string) => line.trim()); + lines.forEach((line: string) => { + buildStore.addLog(buildId, `[kaniko-error] ${line}`); + }); + }); + + dockerProcess.on("close", (code) => { + buildStore.addLog(buildId, `Docker process closed with exit code: ${code}`); + buildStore.updateStatus(buildId, { type: "finishing", data: {} }); + + if (code === 0) { + resolve(); + } else { + buildStore.updateStatus(buildId, { + type: "failure", + data: { reason: `Container exited with code ${code}` }, + }); + reject(new Error(`Container exited with code ${code}`)); + } + }); + + dockerProcess.on("spawn", () => { + buildStore.addLog(buildId, "Docker process spawned successfully"); + }); + + dockerProcess.on("error", (error) => { + buildStore.addLog(buildId, `Docker process error: ${error.message}`); + buildStore.updateStatus(buildId, { + type: "failure", + data: { reason: `Failed to start kaniko: ${error.message}` }, + }); + reject(error); + }); + }); +} + + diff --git a/cloud/packages/ci-manager/src/executors/rivet.ts b/cloud/packages/ci-manager/src/executors/rivet.ts new file mode 100644 index 0000000000..936498566e --- /dev/null +++ b/cloud/packages/ci-manager/src/executors/rivet.ts @@ -0,0 +1,172 @@ +import { RivetClient } from "@rivet-gg/api"; +import { BuildStore } from "../build-store"; + +export async function runRivetBuild( + buildStore: BuildStore, + serverUrl: string, + buildId: string, +): Promise { + const token = process.env.RIVET_CLOUD_TOKEN; + if (!token) { + throw new Error("RIVET_CLOUD_TOKEN environment variable is required"); + } + + const projectId = process.env.RIVET_PROJECT!; + if (!projectId) { + throw new Error("RIVET_PROJECT environment variable is required"); + } + + const environmentName = process.env.RIVET_ENVIRONMENT!; + if (!environmentName) { + throw new Error("RIVET_ENVIRONMENT environment variable is required"); + } + + const kanikoBuildId = process.env.KANIKO_BUILD_ID!; + if (!kanikoBuildId) { + throw new Error("KANIKO_BUILD_ID environment variable is required"); + } + + const client = new RivetClient({ token }); + + const build = buildStore.getBuild(buildId); + if (!build) { + throw new Error(`Build ${buildId} not found`); + } + + const contextUrl = `${serverUrl}/builds/${buildId}/kaniko/context.tar.gz`; + const outputUrl = `${serverUrl}/builds/${buildId}/kaniko/output.tar.gz`; + + buildStore.addLog(buildId, "Creating Rivet actor for kaniko build..."); + + try { + const createResponse = await client.actors.create({ + project: projectId, + environment: environmentName, + body: { + tags: { + name: "ci-runner", + }, + build: kanikoBuildId, + runtime: { + environment: { + CONTEXT_URL: contextUrl, + OUTPUT_URL: outputUrl, + DESTINATION: `${buildId}:latest`, + DOCKERFILE_PATH: build.dockerfilePath!, + }, + }, + network: { + ports: {}, + waitReady: false, + }, + resources: { + cpu: 1000, + memory: 1024, + }, + lifecycle: { + killTimeout: 300000, + durable: false, + }, + }, + }); + + const actorId = createResponse.actor.id; + buildStore.addLog(buildId, `Created Rivet actor: ${actorId}`); + + await pollActorStatus( + buildStore, + client, + projectId, + environmentName, + buildId, + actorId, + ); + } catch (error: any) { + buildStore.addLog( + buildId, + `Failed to create Rivet actor: ${error.message}`, + ); + buildStore.updateStatus(buildId, { + type: "failure", + data: { reason: `Failed to create Rivet actor: ${error.message}` }, + }); + } +} + +async function pollActorStatus( + buildStore: BuildStore, + client: RivetClient, + projectId: string, + environmentName: string, + buildId: string, + actorId: string, +): Promise { + const pollInterval = 2000; + const maxPolls = 300; + let pollCount = 0; + + while (true) { + try { + pollCount++; + if (pollCount > maxPolls) { + buildStore.addLog(buildId, "Polling timeout reached"); + buildStore.updateStatus(buildId, { + type: "failure", + data: { reason: "Actor polling timeout" }, + }); + return; + } + + const { actor } = await client.actors.get(actorId, { + project: projectId, + environment: environmentName, + }); + + let state: string; + if (actor.destroyedAt && actor.startedAt) { + if (actor.startedAt) { + state = "stopped"; + } else { + state = "crashed"; + } + } else if (actor.startedAt) { + state = "running"; + } else { + state = "starting"; + } + + buildStore.addLog(buildId, `Actor status: ${state}`); + + if (state === "stopped") { + buildStore.addLog(buildId, `Actor stopped.`); + return; + } + + if (state === "crashed") { + buildStore.updateStatus(buildId, { + type: "failure", + data: { reason: `Actor crashed` }, + }); + return; + } + + if (state === "running" || state === "starting") { + await new Promise((resolve) => setTimeout(resolve, 1000)); + } else { + buildStore.addLog(buildId, `Unexpected actor state: ${state}`); + buildStore.updateStatus(buildId, { + type: "failure", + data: { reason: `Unexpected actor state: ${state}` }, + }); + return; + } + } catch (error: any) { + buildStore.addLog(buildId, `Error polling actor: ${error.message}`); + buildStore.updateStatus(buildId, { + type: "failure", + data: { reason: `Error polling actor: ${error.message}` }, + }); + return; + } + } +} diff --git a/cloud/packages/ci-manager/src/index.ts b/cloud/packages/ci-manager/src/index.ts new file mode 100644 index 0000000000..5720134d1f --- /dev/null +++ b/cloud/packages/ci-manager/src/index.ts @@ -0,0 +1,4 @@ +import { createServer } from "./server"; + +console.log("CI Manager starting on port 3000"); +createServer(3000); diff --git a/cloud/packages/ci-manager/src/kaniko-runner.ts b/cloud/packages/ci-manager/src/kaniko-runner.ts new file mode 100644 index 0000000000..86a6dd24b8 --- /dev/null +++ b/cloud/packages/ci-manager/src/kaniko-runner.ts @@ -0,0 +1,58 @@ +import { BuildStore } from "./build-store"; +import { mkdir } from "node:fs/promises"; +import { existsSync } from "node:fs"; +import { dirname } from "node:path"; +import { runDockerBuild } from "./executors/docker"; +import { runRivetBuild } from "./executors/rivet"; + +export async function runKanikoBuild( + buildStore: BuildStore, + serverUrl: string, + buildId: string, +): Promise { + const build = buildStore.getBuild(buildId); + if (!build) { + throw new Error(`Build ${buildId} not found`); + } + + await mkdir(dirname(build.contextPath!), { recursive: true }); + + buildStore.updateStatus(buildId, { type: "running", data: {} }); + + const executionMode = process.env.KANIKO_EXECUTION_MODE || "docker"; + buildStore.addLog(buildId, `Using execution mode: ${executionMode}`); + + if (executionMode === "rivet") { + await runRivetBuild(buildStore, serverUrl, buildId); + } else { + await runDockerBuild(buildStore, serverUrl, buildId); + } + + // Add upload validation check + await validateBuildUpload(buildStore, buildId); +} + +async function validateBuildUpload( + buildStore: BuildStore, + buildId: string, +): Promise { + const build = buildStore.getBuild(buildId); + if (!build || !build.outputPath) { + buildStore.updateStatus(buildId, { + type: "failure", + data: { reason: "Build not found or missing output path" }, + }); + return; + } + + if (existsSync(build.outputPath)) { + buildStore.addLog(buildId, "Build upload validated successfully"); + } else { + buildStore.updateStatus(buildId, { + type: "failure", + data: { + reason: "Build output file was not uploaded after waiting", + }, + }); + } +} diff --git a/cloud/packages/ci-manager/src/oci-converter.ts b/cloud/packages/ci-manager/src/oci-converter.ts new file mode 100644 index 0000000000..5b4992877c --- /dev/null +++ b/cloud/packages/ci-manager/src/oci-converter.ts @@ -0,0 +1,83 @@ +import { execSync } from "child_process"; +import { mkdir, rm, writeFile, readFile, readdir, stat } from "fs/promises"; +import { join, dirname } from "path"; +import { createReadStream, createWriteStream } from "fs"; +import { pipeline } from "stream/promises"; +import * as tar from "tar"; + +export interface OCIConversionResult { + bundleTarPath: string; + cleanup: () => Promise; +} + +export async function convertDockerTarToOCIBundle( + dockerTarPath: string, + tempDir: string = "/tmp/oci-conversion" +): Promise { + const conversionId = Math.random().toString(36).substring(7); + const workDir = join(tempDir, conversionId); + + try { + await mkdir(workDir, { recursive: true }); + + const dockerImagePath = join(workDir, "docker-image.tar"); + const ociImagePath = join(workDir, "oci-image"); + const ociBundlePath = join(workDir, "oci-bundle"); + const bundleTarPath = join(workDir, "oci-bundle.tar"); + + // Extract docker tar if it's compressed + const dockerTarData = await readFile(dockerTarPath); + await writeFile(dockerImagePath, dockerTarData); + + // Convert Docker image to OCI image using skopeo + console.log(`Converting Docker image to OCI image: ${dockerImagePath} -> ${ociImagePath}`); + execSync(`skopeo copy docker-archive:${dockerImagePath} oci:${ociImagePath}:default`, { + stdio: "pipe" + }); + + // Convert OCI image to OCI bundle using umoci + console.log(`Converting OCI image to OCI bundle: ${ociImagePath} -> ${ociBundlePath}`); + execSync(`umoci unpack --rootless --image ${ociImagePath}:default ${ociBundlePath}`, { + stdio: "pipe" + }); + + // Create tar from OCI bundle + console.log(`Creating tar from OCI bundle: ${ociBundlePath} -> ${bundleTarPath}`); + await tar.create( + { + file: bundleTarPath, + cwd: ociBundlePath, + }, + ["."] + ); + + // Clean up intermediate files + await Promise.all([ + rm(dockerImagePath, { force: true }), + rm(ociImagePath, { recursive: true, force: true }), + rm(ociBundlePath, { recursive: true, force: true }) + ]); + + const cleanup = async () => { + try { + await rm(workDir, { recursive: true, force: true }); + } catch (error) { + console.warn(`Failed to cleanup OCI conversion directory ${workDir}:`, error); + } + }; + + return { + bundleTarPath, + cleanup + }; + } catch (error) { + // Cleanup on error + try { + await rm(workDir, { recursive: true, force: true }); + } catch (cleanupError) { + console.warn(`Failed to cleanup after error in ${workDir}:`, cleanupError); + } + throw new Error(`OCI conversion failed: ${error}`); + } +} + diff --git a/cloud/packages/ci-manager/src/rivet-uploader.ts b/cloud/packages/ci-manager/src/rivet-uploader.ts new file mode 100644 index 0000000000..6107c7d4ea --- /dev/null +++ b/cloud/packages/ci-manager/src/rivet-uploader.ts @@ -0,0 +1,235 @@ +import { RivetClient } from "@rivet-gg/api"; +import { warn } from "console"; +import { createReadStream, statSync } from "fs"; +import { readFile } from "fs/promises"; + +export interface RivetUploadConfig { + token: string; + project?: string; + environment?: string; +} + +export interface RivetUploadResult { + buildId: string; +} + +export async function uploadOCIBundleToRivet( + bundleTarPath: string, + buildName: string, + imageTag: string, + config: RivetUploadConfig, + buildVersion: string, + extraTags?: Record, +): Promise { + const client = new RivetClient({ token: config.token }); + + try { + // Get file stats + const stats = statSync(bundleTarPath); + const fileSize = stats.size; + + console.log( + `Preparing Rivet upload for ${bundleTarPath} (${fileSize} bytes)`, + ); + + // Prepare the build upload + const prepareResponse = await client.builds.prepare({ + project: config.project, + environment: config.environment, + body: { + imageTag, + imageFile: { + path: "oci-bundle.tar", + contentType: "application/x-tar", + contentLength: fileSize, + }, + kind: "oci_bundle", + compression: "none", + }, + }); + + const buildId = prepareResponse.build; + const presignedRequests = prepareResponse.presignedRequests; + + console.log(`Rivet build prepared: ${buildId}`); + console.log(`Upload chunks: ${presignedRequests.length}`); + + // Upload chunks in parallel + const uploadPromises = presignedRequests.map(async (request, index) => { + const { url, byteOffset, contentLength } = request; + + console.log( + `Uploading chunk ${index + 1}/${presignedRequests.length}: offset=${byteOffset}, size=${contentLength}`, + ); + + // Read the specific chunk + const buffer = Buffer.alloc(contentLength); + const fileHandle = await import("fs/promises").then((fs) => + fs.open(bundleTarPath, "r"), + ); + try { + await fileHandle.read(buffer, 0, contentLength, byteOffset); + } finally { + await fileHandle.close(); + } + + // Upload chunk with retries + await uploadChunkWithRetry(url, buffer, 3); + + console.log( + `Chunk ${index + 1}/${presignedRequests.length} uploaded successfully`, + ); + }); + + // Wait for all chunks to upload + await Promise.all(uploadPromises); + + console.log(`All chunks uploaded for build ${buildId}`); + + // Complete the build + await client.builds.complete(buildId, { + project: config.project, + environment: config.environment, + }); + + console.log(`Rivet build completed: ${buildId}`); + + // Patch tags: remove "current" from existing builds with same name, then set current on new build + await patchBuildTags( + client, + buildId, + buildName, + config, + buildVersion, + extraTags, + ); + + return { buildId }; + } catch (error) { + throw new Error(`Rivet upload failed: ${error}`); + } +} + +async function uploadChunkWithRetry( + url: string, + buffer: Buffer, + maxRetries: number = 3, +): Promise { + let lastError: Error | null = null; + + for (let attempt = 1; attempt <= maxRetries; attempt++) { + try { + const response = await fetch(url, { + method: "PUT", + body: buffer, + headers: { + "Content-Type": "application/octet-stream", + "Content-Length": buffer.length.toString(), + }, + }); + + if (!response.ok) { + throw new Error( + `HTTP ${response.status}: ${response.statusText}`, + ); + } + + return; // Success + } catch (error) { + lastError = + error instanceof Error ? error : new Error(String(error)); + console.warn( + `Upload attempt ${attempt}/${maxRetries} failed:`, + lastError.message, + ); + + if (attempt < maxRetries) { + // Exponential backoff: 1s, 2s, 4s + const delay = Math.pow(2, attempt - 1) * 1000; + await new Promise((resolve) => setTimeout(resolve, delay)); + } + } + } + + throw new Error( + `Upload failed after ${maxRetries} attempts: ${lastError?.message}`, + ); +} + +async function patchBuildTags( + client: RivetClient, + buildId: string, + buildName: string, + config: RivetUploadConfig, + buildVersion: string, + extraTags?: Record, +): Promise { + try { + console.log( + `Patching tags for build ${buildId} with name: ${buildName}`, + ); + + // Step 1: Find existing builds with the same name and current=true + const tagsFilter = JSON.stringify({ + name: buildName, + current: "true", + }); + + const listResponse = await client.builds.list({ + project: config.project, + environment: config.environment, + tagsJson: tagsFilter, + }); + + console.log( + `Found ${listResponse.builds.length} existing builds with current tag`, + ); + + // Step 2: Remove "current" tag from all existing builds with the same name + for (const build of listResponse.builds) { + try { + await client.builds.patchTags(build.id, { + project: config.project, + environment: config.environment, + body: { + tags: { + current: null, + }, + }, + }); + console.log(`Removed current tag from build ${build.id}`); + } catch (error) { + console.warn( + `Failed to remove current tag from build ${build.id}:`, + error, + ); + } + } + + // Step 3: Set tags on the new build + const tags: Record = { + name: buildName, + version: buildVersion, + current: "true", + }; + + // Add extra tags if provided + if (extraTags) { + Object.assign(tags, extraTags); + } + + await client.builds.patchTags(buildId, { + project: config.project, + environment: config.environment, + body: { + tags, + }, + }); + + console.log(`Successfully patched tags for build ${buildId}`); + } catch (error) { + console.warn(`Failed to patch tags for build ${buildId}:`, error); + // Don't throw here to avoid failing the entire upload process + } +} + diff --git a/cloud/packages/ci-manager/src/server.ts b/cloud/packages/ci-manager/src/server.ts new file mode 100644 index 0000000000..c4e3ad3f6b --- /dev/null +++ b/cloud/packages/ci-manager/src/server.ts @@ -0,0 +1,321 @@ +import { Hono } from "hono"; +import { streamSSE } from "hono/streaming"; +import { logger } from "hono/logger"; +import { BuildStore } from "./build-store"; +import { runKanikoBuild } from "./kaniko-runner"; +import { createWriteStream, createReadStream } from "node:fs"; +import { mkdir, stat } from "node:fs/promises"; +import { dirname } from "path"; +import { Readable } from "node:stream"; +import { pipeline } from "node:stream/promises"; +import { serve } from "@hono/node-server"; +import type { ReadableStream as WebReadableStream } from "stream/web"; +import { + convertDockerTarToOCIBundle, +} from "./oci-converter"; +import { + uploadOCIBundleToRivet, + type RivetUploadConfig, +} from "./rivet-uploader"; + +async function processRivetUpload( + buildStore: BuildStore, + buildId: string, +): Promise { + const build = buildStore.getBuild(buildId); + if (!build || !build.outputPath) { + throw new Error(`Build ${buildId} not found or missing output path`); + } + + try { + // Check if Rivet upload is enabled + const rivetToken = process.env.RIVET_CLOUD_TOKEN; + const rivetProject = process.env.RIVET_PROJECT; + const rivetEnvironment = process.env.RIVET_ENVIRONMENT; + + if (!rivetToken || !rivetProject || !rivetEnvironment) { + throw new Error( + "Rivet upload failed - missing RIVET_CLOUD_TOKEN, RIVET_PROJECT, or RIVET_ENVIRONMENT", + ); + } + + const rivetConfig: RivetUploadConfig = { + token: rivetToken, + project: rivetProject, + environment: build.environmentId, + }; + + // Step 1: Convert to OCI bundle + buildStore.updateStatus(buildId, { type: "converting", data: {} }); + buildStore.addLog(buildId, "Converting Docker image to OCI bundle..."); + + const conversionResult = await convertDockerTarToOCIBundle( + build.outputPath, + ); + + try { + // Step 2: Upload to Rivet + buildStore.updateStatus(buildId, { + type: "uploading", + data: {}, + }); + buildStore.addLog(buildId, "Uploading OCI bundle to Rivet..."); + + const uploadResult = await uploadOCIBundleToRivet( + conversionResult.bundleTarPath, + build.buildName!, + `${buildId}:latest`, // Match kaniko destination format + rivetConfig, + new Date().toISOString(), // Use timestamp as version for now + ); + + buildStore.addLog( + buildId, + `Successfully uploaded to Rivet: ${uploadResult.buildId}`, + ); + buildStore.updateStatus(buildId, { + type: "success", + data: { buildId: uploadResult.buildId }, + }); + } finally { + await conversionResult.cleanup(); + } + } catch (error) { + buildStore.updateStatus(buildId, { + type: "failure", + data: { reason: `Rivet upload process failed: ${error}` }, + }); + buildStore.addLog(buildId, `Rivet upload process failed: ${error}`); + throw error; + } +} + +export async function createServer(port: number = 3000) { + const app = new Hono(); + + app.use(logger()); + + const buildStore = new BuildStore(); + await buildStore.init(); + + app.post("/builds", async (c) => { + try { + const formData = await c.req.formData(); + const buildName = formData.get("buildName") as string; + const dockerfilePath = formData.get("dockerfilePath") as string; + const environmentId = formData.get("environmentId") as string; + const contextFile = formData.get("context") as File; + + if (!buildName) { + return c.json({ error: "buildName is required" }, 400); + } + + if (!dockerfilePath) { + return c.json({ error: "dockerfilePath is required" }, 400); + } + + if (!environmentId) { + return c.json({ error: "environmentId is required" }, 400); + } + + if (!contextFile) { + return c.json({ error: "context file is required" }, 400); + } + + // Create the build + const buildId = buildStore.createBuild(buildName, dockerfilePath, environmentId); + const contextPath = buildStore.getContextPath(buildId); + + if (!contextPath) { + return c.json({ error: "Failed to create build" }, 500); + } + + // Save the context file + await mkdir(dirname(contextPath), { recursive: true }); + + const contextBuffer = await contextFile.arrayBuffer(); + const fileStream = createWriteStream(contextPath); + fileStream.write(new Uint8Array(contextBuffer)); + fileStream.end(); + + buildStore.addLog(buildId, "Context uploaded successfully"); + + // Run build in background + buildStore.addLog(buildId, "About to start kaniko runner"); + + const serverUrlParam = c.req.query("serverUrl"); + const serverUrl = serverUrlParam || new URL(c.req.url).origin; + buildStore.addLog(buildId, `Using server URL: ${serverUrl}`); + + try { + runKanikoBuild(buildStore, serverUrl, buildId).catch( + (error) => { + buildStore.addLog( + buildId, + `Failed to start build: ${error}`, + ); + buildStore.updateStatus(buildId, { + type: "failure", + data: { reason: `Failed to start build: ${error}` }, + }); + }, + ); + } catch (error) { + buildStore.addLog( + buildId, + `Sync error starting build: ${error}`, + ); + } + + return c.json({ buildId }); + } catch (error) { + return c.json({ error: "Failed to process build request" }, 500); + } + }); + + app.get("/builds/:id", async (c) => { + const buildId = c.req.param("id"); + const build = buildStore.getBuild(buildId); + + if (!build) { + return c.json({ error: "Build not found" }, 404); + } + + return c.json({ + id: build.id, + status: build.status, + }); + }); + + app.get("/builds/:id/events", async (c) => { + const buildId = c.req.param("id"); + const build = buildStore.getBuild(buildId); + + if (!build) { + return c.json({ error: "Build not found" }, 404); + } + + return streamSSE(c, async (stream) => { + await stream.writeSSE({ data: "connected" }); + + for (const event of build.events) { + await stream.writeSSE({ data: JSON.stringify(event) }); + } + + const unsubscribe = buildStore.emitter.on( + "build-event", + async (eventBuildId, event) => { + if (eventBuildId === buildId) { + await stream.writeSSE({ data: JSON.stringify(event) }); + } + }, + ); + + let resolve: () => void; + const abortPromise = new Promise((res) => { + resolve = res; + }); + + stream.onAbort(() => { + unsubscribe(); + resolve(); + }); + + await abortPromise; + }); + }); + + app.get("/builds/:id/kaniko/context.tar.gz", async (c) => { + const buildId = c.req.param("id"); + console.log(`[SERVER] Kaniko requesting context for build ${buildId}`); + const contextPath = buildStore.getContextPath(buildId); + + if (!contextPath) { + return c.json({ error: "Build not found" }, 404); + } + + try { + const fileStream = createReadStream(contextPath); + return new Response(fileStream as any, { + headers: { + "content-type": "application/gzip", + "content-disposition": + "attachment; filename=context.tar.gz", + }, + }); + } catch (error) { + return c.json({ error: "Context file not found" }, 404); + } + }); + + app.get("/builds/:id/output.tar.gz", async (c) => { + const buildId = c.req.param("id"); + const outputPath = buildStore.getOutputPath(buildId); + + if (!outputPath) { + return c.json({ error: "Build not found" }, 404); + } + + try { + const fileStream = createReadStream(outputPath); + + // Mark as downloaded to trigger cleanup + buildStore.markDownloaded(buildId); + + return new Response(fileStream as any, { + headers: { + "content-type": "application/gzip", + "content-disposition": "attachment; filename=output.tar.gz", + }, + }); + } catch (error) { + return c.json({ error: "Output file not found" }, 404); + } + }); + + app.put("/builds/:id/kaniko/output.tar.gz", async (c) => { + const buildId = c.req.param("id"); + console.log(`[SERVER] Kaniko uploading output for build ${buildId}`); + const outputPath = buildStore.getOutputPath(buildId); + + if (!outputPath) { + return c.json({ error: "Build not found" }, 404); + } + + try { + await mkdir(dirname(outputPath), { recursive: true }); + + const body = c.req.raw.body; + if (!body) return c.json({ error: "Body does not exist" }, 400); + + const nodeStream = Readable.fromWeb(body as WebReadableStream); + const writeStream = createWriteStream(outputPath); + await pipeline(nodeStream, writeStream); + + // Log upload details + const stats = await stat(outputPath); + buildStore.addLog( + buildId, + `Kaniko output uploaded successfully: ${outputPath} (${stats.size} bytes)`, + ); + + // Start Rivet upload process in background + processRivetUpload(buildStore, buildId).catch((error) => { + buildStore.addLog(buildId, `Rivet upload failed: ${error}`); + buildStore.updateStatus(buildId, { + type: "failure", + data: { reason: `Rivet upload failed: ${error}` }, + }); + }); + + return c.json({ message: "File saved successfully" }); + } catch (error) { + return c.json({ error: "Failed to create output file" }, 500); + } + }); + + return serve({ + fetch: app.fetch, + port, + }); +} diff --git a/cloud/packages/ci-manager/src/types.ts b/cloud/packages/ci-manager/src/types.ts new file mode 100644 index 0000000000..f66f4b2281 --- /dev/null +++ b/cloud/packages/ci-manager/src/types.ts @@ -0,0 +1,43 @@ +import { z } from "zod"; + +export const StatusSchema = z.discriminatedUnion("type", [ + z.object({ type: z.literal("starting"), data: z.object({}) }), + z.object({ type: z.literal("running"), data: z.object({}) }), + z.object({ type: z.literal("finishing"), data: z.object({}) }), + z.object({ type: z.literal("converting"), data: z.object({}) }), + z.object({ type: z.literal("uploading"), data: z.object({}) }), + z.object({ type: z.literal("failure"), data: z.object({ reason: z.string() }) }), + z.object({ type: z.literal("success"), data: z.object({ buildId: z.string() }) }), +]); + +export type Status = z.infer; + +export const BuildRequestSchema = z.object({ + buildName: z.string(), + dockerfilePath: z.string(), + environmentId: z.string(), +}); + +export type BuildRequest = z.infer; + +export const BuildEventSchema = z.discriminatedUnion("type", [ + z.object({ type: z.literal("status"), data: StatusSchema }), + z.object({ type: z.literal("log"), data: z.object({ line: z.string() }) }), +]); + +export type BuildEvent = z.infer; + +export interface BuildInfo { + id: string; + status: Status; + buildName?: string; + dockerfilePath?: string; + environmentId?: string; + contextPath?: string; + outputPath?: string; + events: BuildEvent[]; + containerProcess?: any; + createdAt: Date; + downloadedAt?: Date; + cleanupTimeout?: NodeJS.Timeout; +} diff --git a/cloud/packages/ci-manager/tests/docker-e2e.test.ts b/cloud/packages/ci-manager/tests/docker-e2e.test.ts new file mode 100644 index 0000000000..5245435444 --- /dev/null +++ b/cloud/packages/ci-manager/tests/docker-e2e.test.ts @@ -0,0 +1,227 @@ +/** + * This test is intended to check that Kaniko works as intended with an inline driver (not using Rivet). + * + * Useful for quick iteration on the server. + */ + +import { describe, it, expect, beforeAll, afterAll, test } from "vitest"; +import { execSync } from "node:child_process"; +import { join } from "node:path"; +import { writeFile } from "fs/promises"; +import getPort from "get-port"; +import { createServer } from "../src/server"; +import { RivetClient } from "@rivet-gg/api"; +import { + createSampleDockerContext, + createFailingDockerContext, + createTestWebServerContext, + createBuildWithContext, + getBuildStatus, + pollBuildStatus, + downloadOutputTar, + waitForActorReady, + testActorEndpoint, + createActorFromBuild, +} from "./test-utils"; +import { convertDockerTarToOCIBundle } from "../src/oci-converter"; +import { + uploadOCIBundleToRivet, + type RivetUploadConfig, +} from "../src/rivet-uploader"; + +describe("Docker", () => { + let server: any; + let baseUrl: string; + let rivetConfig: RivetUploadConfig = undefined as any; + let testActorIds: string[] = []; + + beforeAll(async () => { + // Build the ci-manager dockerfile before starting tests + console.log("Building ci-runner Docker image..."); + execSync("docker build -t ci-runner .", { + cwd: join(__dirname, "../../ci-runner"), + stdio: "inherit", + }); + console.log("ci-runner Docker image built successfully"); + + const port = await getPort(); + server = await createServer(port); + baseUrl = `http://localhost:${port}`; + + // Initialize Rivet config if environment variables are available + const token = process.env.RIVET_CLOUD_TOKEN; + const project = process.env.RIVET_PROJECT; + const environment = process.env.RIVET_ENVIRONMENT; + + if (token && project && environment) { + rivetConfig = { token, project, environment }; + console.log("Rivet config initialized - will test actor creation"); + } else { + throw new Error( + "Rivet config not available - skipping actor creation tests", + ); + } + }); + + afterAll(async () => { + // Clean up test actors + const client = new RivetClient({ token: rivetConfig.token }); + for (const actorId of testActorIds) { + try { + await client.actors.destroy(actorId, { + project: rivetConfig.project, + environment: rivetConfig.environment, + }); + console.log(`Cleaned up test actor: ${actorId}`); + } catch (error) { + console.warn(`Failed to cleanup test actor ${actorId}:`, error); + } + } + + if (server) { + if (typeof server.stop === "function") { + server.stop(); + } else if (typeof server.close === "function") { + server.close(); + } + } + }); + + it("full e2e", async () => { + console.log("Starting E2E CI Manager Test"); + + // Create sample Docker context with web server + console.log("Creating sample Docker context with web server..."); + const contextBuffer = await createTestWebServerContext(); + console.log(`Context created (${contextBuffer.length} bytes)`); + expect(contextBuffer.length).toBeGreaterThan(0); + + // Create build with context + console.log("Creating build with context..."); + const buildName = "test-build-" + Date.now(); + const buildId = await createBuildWithContext( + baseUrl, + buildName, + "configs/build.dockerfile", + contextBuffer, + rivetConfig.environment, + ); + console.log(`Build created and started: ${buildId}`); + expect(buildId).toBeDefined(); + expect(typeof buildId).toBe("string"); + + // Poll build status until completion + console.log("Polling build status..."); + const buildResult = await pollBuildStatus(baseUrl, buildId); + console.log(`Build completed with status: ${buildResult.status}`); + + // The build should actually succeed since we have Kaniko available + expect(buildResult.status).toBe("success"); + + console.log("Build completed successfully!"); + + // Get final build status + console.log("Checking final build status:"); + const buildStatus = await getBuildStatus(baseUrl, buildId); + console.log(buildStatus); + expect(buildStatus.id).toBe(buildId); + expect(buildStatus.status.type).toBe("success"); + + let actorId: string | undefined; + + // Create actor from build + console.log("Creating actor from build..."); + const actorResult = await createActorFromBuild( + buildResult.buildId, + buildName, + rivetConfig, + ); + + actorId = actorResult.actorId; + testActorIds.push(actorId); + + expect(actorResult.endpoint).toBeDefined(); + + console.log(`Actor created: ${actorId}`); + console.log(`Actor endpoint: ${actorResult.endpoint}`); + + // Wait for actor to be ready and test endpoint + console.log("Testing actor HTTP endpoint..."); + const testResponse = await testActorEndpoint(actorResult.endpoint); + + expect(testResponse).toBeDefined(); + expect(testResponse.message).toBe("Rivet test successful!"); + expect(testResponse.timestamp).toBeDefined(); + expect(testResponse.hostname).toBeDefined(); + + console.log("E2E Test completed successfully!"); + }, 600000); // Increase timeout to 10 minutes for the full workflow including Rivet + + it("should handle build not found", async () => { + const response = await fetch(`${baseUrl}/builds/non-existent-build`); + expect(response.status).toBe(404); + + const result = await response.json(); + expect(result.error).toBe("Build not found"); + }); + + it("should reject build creation with missing data", async () => { + const formData = new FormData(); + formData.append("buildName", "test-build"); + // Missing dockerfilePath and context file + + const response = await fetch(`${baseUrl}/builds`, { + method: "POST", + body: formData, + }); + + expect(response.status).toBe(400); + + const result = await response.json(); + expect(result.error).toBe("dockerfilePath is required"); + }); + + it("should handle failing dockerfile build correctly", async () => { + console.log("Starting failing dockerfile test"); + + // Create failing Docker context + console.log("Creating failing Docker context..."); + const contextBuffer = await createFailingDockerContext(); + console.log(`Failing context created (${contextBuffer.length} bytes)`); + expect(contextBuffer.length).toBeGreaterThan(0); + + // Create build with failing context + console.log("Creating build with failing context..."); + const buildName = "test-failing-build-" + Date.now(); + const buildId = await createBuildWithContext( + baseUrl, + buildName, + "configs/fail.dockerfile", + contextBuffer, + rivetConfig.environment, + ); + console.log(`Failing build created: ${buildId}`); + expect(buildId).toBeTruthy(); + + // Poll build status until failure + console.log("Polling build status for failure..."); + const buildResult = await pollBuildStatus(baseUrl, buildId); + console.log(`Build completed with status: ${buildResult.status}`); + + // Verify build completed with failure status + expect(buildResult.status).toBe("failure"); + + // Check final build status via API + console.log("Checking final build status:"); + const buildStatus = await getBuildStatus(baseUrl, buildId); + console.log(buildStatus); + expect(buildStatus.id).toBe(buildId); + expect(buildStatus.status.type).toBe("failure"); + + // Get final build status to verify failure reason + const finalBuildStatus = await getBuildStatus(baseUrl, buildId); + expect(finalBuildStatus.status.data.reason).toBeTruthy(); + + console.log("Failing dockerfile test completed successfully!"); + }, 70000); // 70 second timeout for failing build test +}); diff --git a/cloud/packages/ci-manager/tests/oci-converter.test.ts b/cloud/packages/ci-manager/tests/oci-converter.test.ts new file mode 100644 index 0000000000..9eeed5b432 --- /dev/null +++ b/cloud/packages/ci-manager/tests/oci-converter.test.ts @@ -0,0 +1,203 @@ +import { test, expect, beforeAll, afterAll } from "vitest"; +import { execSync } from "child_process"; +import { mkdir, writeFile, rm, readFile } from "fs/promises"; +import { join } from "path"; +import * as tar from "tar"; +import { convertDockerTarToOCIBundle } from "../src/oci-converter"; + +const TEST_DIR = "/tmp/oci-converter-test"; +const TEST_IMAGE_NAME = "oci-converter-test"; + +async function createTestDockerImage(): Promise { + const contextDir = join(TEST_DIR, "docker-context"); + await mkdir(contextDir, { recursive: true }); + + // Create a simple Dockerfile + const dockerfile = ` +FROM alpine:latest +RUN echo "Hello from OCI converter test!" > /hello.txt +COPY test-script.sh /test-script.sh +RUN chmod +x /test-script.sh +CMD ["/test-script.sh"] +`; + + // Create a test script + const testScript = `#!/bin/sh +echo "OCI conversion test successful!" +cat /hello.txt +`; + + await writeFile(join(contextDir, "Dockerfile"), dockerfile.trim()); + await writeFile(join(contextDir, "test-script.sh"), testScript.trim()); + + // Build the Docker image + console.log(`Building test Docker image: ${TEST_IMAGE_NAME}`); + execSync(`docker build -t ${TEST_IMAGE_NAME} .`, { + cwd: contextDir, + stdio: "pipe" + }); + + // Save the Docker image to tar + const dockerTarPath = join(TEST_DIR, "test-image.tar"); + console.log(`Saving Docker image to: ${dockerTarPath}`); + execSync(`docker save -o ${dockerTarPath} ${TEST_IMAGE_NAME}`, { + stdio: "pipe" + }); + + return dockerTarPath; +} + +async function createMockKanikoOutput(dockerTarPath: string): Promise { + const kanikoOutputPath = join(TEST_DIR, "kaniko-output.tar.gz"); + const tempDir = join(TEST_DIR, "kaniko-temp"); + + await mkdir(tempDir, { recursive: true }); + + // Copy docker tar to the expected location inside kaniko output + const dockerTarData = await readFile(dockerTarPath); + await writeFile(join(tempDir, "image.tar"), dockerTarData); + + // Create kaniko output tar.gz + await tar.create( + { + file: kanikoOutputPath, + gzip: true, + cwd: tempDir + }, + ["."] + ); + + // Cleanup temp directory + await rm(tempDir, { recursive: true, force: true }); + + return kanikoOutputPath; +} + +async function validateOCIBundle(bundleTarPath: string): Promise { + const validateDir = join(TEST_DIR, "validate"); + await mkdir(validateDir, { recursive: true }); + + try { + // Extract the OCI bundle tar + await tar.extract({ + file: bundleTarPath, + cwd: validateDir + }); + + // Check for required OCI bundle files + const configJsonPath = join(validateDir, "config.json"); + const rootfsPath = join(validateDir, "rootfs"); + + // Verify config.json exists and is valid JSON + const configData = await readFile(configJsonPath, "utf8"); + const config = JSON.parse(configData); + + expect(config).toBeDefined(); + expect(config.ociVersion).toBeDefined(); + expect(config.process).toBeDefined(); + expect(config.root).toBeDefined(); + + // Verify rootfs directory exists + const rootfsStat = await import("fs/promises").then(fs => fs.stat(rootfsPath)); + expect(rootfsStat.isDirectory()).toBe(true); + + console.log("OCI bundle validation passed"); + + } finally { + await rm(validateDir, { recursive: true, force: true }); + } +} + +beforeAll(async () => { + // Create test directory + await mkdir(TEST_DIR, { recursive: true }); + + // Check if Docker is available + try { + execSync("docker --version", { stdio: "pipe" }); + } catch (error) { + throw new Error("Docker is not available. Please install Docker to run OCI converter tests."); + } + + // Check if skopeo is available + try { + execSync("skopeo --version", { stdio: "pipe" }); + } catch (error) { + throw new Error("skopeo is not available. Please install skopeo to run OCI converter tests."); + } + + // Check if umoci is available + try { + execSync("umoci --version", { stdio: "pipe" }); + } catch (error) { + throw new Error("umoci is not available. Please install umoci to run OCI converter tests."); + } +}); + +afterAll(async () => { + // Cleanup test directory + await rm(TEST_DIR, { recursive: true, force: true }); + + // Remove test Docker image + try { + execSync(`docker rmi ${TEST_IMAGE_NAME}`, { stdio: "pipe" }); + } catch (error) { + // Ignore errors when removing image + } +}); + +test("createTestDockerImage builds and saves Docker image", async () => { + const dockerTarPath = await createTestDockerImage(); + + // Verify the tar file was created + const stats = await import("fs/promises").then(fs => fs.stat(dockerTarPath)); + expect(stats.isFile()).toBe(true); + expect(stats.size).toBeGreaterThan(0); + + console.log(`Test Docker image created: ${dockerTarPath} (${stats.size} bytes)`); +}, 60000); + + +test("convertDockerTarToOCIBundle converts Docker tar to OCI bundle", async () => { + const dockerTarPath = await createTestDockerImage(); + + const result = await convertDockerTarToOCIBundle(dockerTarPath); + + try { + // Verify the OCI bundle tar was created + const stats = await import("fs/promises").then(fs => fs.stat(result.bundleTarPath)); + expect(stats.isFile()).toBe(true); + expect(stats.size).toBeGreaterThan(0); + + console.log(`OCI bundle created: ${result.bundleTarPath} (${stats.size} bytes)`); + + // Validate the OCI bundle structure + await validateOCIBundle(result.bundleTarPath); + + } finally { + await result.cleanup(); + } +}, 120000); + +test("full workflow: Docker image -> direct OCI bundle conversion", async () => { + // Create test Docker image + const dockerTarPath = await createTestDockerImage(); + + // Convert directly to OCI bundle (like the new simplified flow) + const convertResult = await convertDockerTarToOCIBundle(dockerTarPath); + + try { + // Verify the final OCI bundle + const stats = await import("fs/promises").then(fs => fs.stat(convertResult.bundleTarPath)); + expect(stats.isFile()).toBe(true); + expect(stats.size).toBeGreaterThan(0); + + // Validate OCI bundle structure + await validateOCIBundle(convertResult.bundleTarPath); + + console.log(`Full workflow completed successfully: ${convertResult.bundleTarPath}`); + + } finally { + await convertResult.cleanup(); + } +}, 180000); \ No newline at end of file diff --git a/cloud/packages/ci-manager/tests/rivet-e2e.test.ts b/cloud/packages/ci-manager/tests/rivet-e2e.test.ts new file mode 100644 index 0000000000..5e1477c56b --- /dev/null +++ b/cloud/packages/ci-manager/tests/rivet-e2e.test.ts @@ -0,0 +1,243 @@ +import { test, expect, beforeAll, afterAll } from "vitest"; +import { execSync } from "child_process"; +import { mkdir, rm } from "fs/promises"; +import { RivetClient } from "@rivet-gg/api"; +import { + createTestWebServerContext, + pollBuildStatus, + waitForActorReady, + testActorEndpoint, + createActorFromBuild, +} from "./test-utils"; +import { type RivetUploadConfig } from "../src/rivet-uploader"; + +const TEST_DIR = "/tmp/rivet-test"; + +let rivetConfig: RivetUploadConfig; +let testActorIds: string[] = []; + +async function findCIManagerActor( + client: RivetClient, + projectId: string, +): Promise { + try { + const actorsResponse = await client.actors.list({ + project: projectId, + environment: "ci", + tagsJson: JSON.stringify({ name: "ci-manager" }), + }); + + const manager = actorsResponse.actors?.find( + (actor) => actor.tags?.name === "ci-manager", + ); + + return manager?.id || null; + } catch (error) { + console.error("Error finding CI manager actor:", error); + return null; + } +} + +async function createCIManagerActor( + client: RivetClient, + projectId: string, + token: string, +): Promise { + const { builds } = await client.builds.list({ + project: projectId, + environment: "ci", + tagsJson: JSON.stringify({ name: "ci-runner", current: "true" }), + }); + if (!builds[0]) throw new Error("Missing ci-runner build"); + + const createResponse = await client.actors.create({ + project: projectId, + environment: "ci", + body: { + tags: { + name: "ci-manager", + }, + buildTags: { + name: "ci-manager", + current: "true", + }, + runtime: { + environment: { + KANIKO_EXECUTION_MODE: "rivet", + KANIKO_BUILD_ID: builds[0].id, + RIVET_CLOUD_TOKEN: token, + RIVET_PROJECT: projectId, + RIVET_ENVIRONMENT: "ci", + }, + }, + network: { + ports: { + http: { protocol: "https", internalPort: 3000 }, + }, + waitReady: true, + }, + resources: { + cpu: 1000, + memory: 1024, + }, + lifecycle: { + killTimeout: 30000, + durable: true, + }, + }, + }); + + return createResponse.actor.id; +} + +async function destroyActor( + actorId: string, + config: RivetUploadConfig, +): Promise { + const client = new RivetClient({ token: config.token }); + + try { + await client.actors.destroy(actorId, { + project: config.project, + environment: config.environment, + }); + + console.log(`Actor destroyed: ${actorId}`); + } catch (error) { + throw new Error(`Failed to destroy actor: ${error}`); + } +} + +beforeAll(async () => { + await mkdir(TEST_DIR, { recursive: true }); + + const token = process.env.RIVET_CLOUD_TOKEN; + const project = process.env.RIVET_PROJECT; + const environment = process.env.RIVET_ENVIRONMENT; + + if (!token || !project || !environment) { + throw new Error( + "Missing required environment variables: RIVET_CLOUD_TOKEN, RIVET_PROJECT, RIVET_ENVIRONMENT", + ); + } + + rivetConfig = { token, project, environment }; + + try { + execSync("docker --version", { stdio: "pipe" }); + } catch (error) { + throw new Error( + "Docker is not available. Please install Docker to run Rivet tests.", + ); + } +}); + +afterAll(async () => { + for (const actorId of testActorIds) { + try { + await destroyActor(actorId, rivetConfig); + console.log(`Cleaned up test actor: ${actorId}`); + } catch (error) { + console.warn(`Failed to cleanup test actor ${actorId}:`, error); + } + } + + await rm(TEST_DIR, { recursive: true, force: true }); +}); + +test("full e2e", async () => { + const token = rivetConfig.token; + const projectId = rivetConfig.project; + const environmentName = rivetConfig.environment; + + const client = new RivetClient({ token }); + + let ciManagerActorId = await findCIManagerActor(client, projectId); + + if (!ciManagerActorId) { + console.log("Creating CI manager actor..."); + ciManagerActorId = await createCIManagerActor(client, projectId, token); + console.log(`Created CI manager actor: ${ciManagerActorId}`); + + await new Promise((resolve) => setTimeout(resolve, 10000)); + } else { + console.log(`Using existing CI manager actor: ${ciManagerActorId}`); + } + + const actorResponse = await client.actors.get(ciManagerActorId, { + project: projectId, + environment: "ci", + }); + + const endpoint = actorResponse.actor.network?.ports?.["http"]?.hostname; + if (!endpoint) { + throw new Error("Actor endpoint not available"); + } + + const serverUrl = `https://${endpoint}`; + console.log(`Using CI manager endpoint: ${serverUrl}`); + + const contextBuffer = await createTestWebServerContext(); + const buildName = "rivet-test-build"; + + const formData = new FormData(); + formData.append("buildName", buildName); + formData.append("dockerfilePath", "configs/build.dockerfile"); + formData.append("environmentId", rivetConfig.environment); + formData.append("context", new Blob([contextBuffer]), "context.tar.gz"); + + const response = await fetch( + `${serverUrl}/builds?serverUrl=${encodeURIComponent(serverUrl)}`, + { + method: "POST", + body: formData, + }, + ); + if (!response.ok) { + console.log( + "Response status", + response.statusText, + await response.text(), + ); + } + + expect(response.ok).toBe(true); + const result = await response.json(); + expect(result.buildId).toBeDefined(); + + const buildId = result.buildId; + console.log(`Started build: ${buildId}`); + + console.log("Polling build status..."); + const buildResult = await pollBuildStatus(serverUrl, buildId); + expect(buildResult.status).toBe("success"); + console.log(`Build completed with status: ${buildResult.status}`); + + console.log("Creating actor from build..."); + const actorResult = await createActorFromBuild( + buildResult.buildId, + buildName, + rivetConfig, + ); + + const actorId = actorResult.actorId; + testActorIds.push(actorId); + expect(actorResult.endpoint).toBeDefined(); + + console.log(`Actor created: ${actorId}`); + console.log(`Actor endpoint: ${actorResult.endpoint}`); + + await waitForActorReady(actorResult.endpoint); + + console.log("Testing actor HTTP endpoint..."); + const testResponse = await testActorEndpoint(actorResult.endpoint); + + expect(testResponse).toBeDefined(); + expect(testResponse.message).toBe("Rivet test successful!"); + expect(testResponse.timestamp).toBeDefined(); + expect(testResponse.hostname).toBeDefined(); + + console.log("Actor HTTP test successful:", response); + + console.log("✅ Full E2E test completed successfully"); +}, 600000); diff --git a/cloud/packages/ci-manager/tests/test-utils.ts b/cloud/packages/ci-manager/tests/test-utils.ts new file mode 100644 index 0000000000..ba4cfb9bfe --- /dev/null +++ b/cloud/packages/ci-manager/tests/test-utils.ts @@ -0,0 +1,358 @@ +import { mkdir, writeFile, readFile, unlink } from "node:fs/promises"; +import { join } from "node:path"; +import { execSync } from "node:child_process"; +import * as tar from "tar"; +import { randomUUID } from "crypto"; + +export async function createFailingDockerContext(): Promise { + const tempDir = `/tmp/docker-context-fail-${Date.now()}-${Math.random().toString(36).substring(2)}`; + await mkdir(tempDir, { recursive: true }); + await mkdir(join(tempDir, "configs"), { recursive: true }); + + const dockerfile = ` +FROM alpine:latest +RUN exit 1 +CMD echo "This should never run" +`; + + await writeFile(join(tempDir, "configs/fail.dockerfile"), dockerfile); + + const tarPath = `/tmp/context-fail-${Date.now()}.tar.gz`; + + await tar.create( + { + gzip: true, + file: tarPath, + cwd: tempDir, + }, + ["."], + ); + + const fileBuffer = await readFile(tarPath); + return fileBuffer; +} + +export async function createTestWebServerImage(): Promise<{ + dockerTarPath: string; + imageName: string; +}> { + const testId = randomUUID(); + const imageName = `rivet-build:${testId}`; + const contextDir = `/tmp/webserver-context-${testId}`; + await mkdir(contextDir, { recursive: true }); + + const dockerfile = ` +FROM node:18-alpine +WORKDIR /app +COPY package.json server.js ./ +RUN npm install +EXPOSE 3000 +CMD ["node", "server.js"] +`; + + const packageJson = { + name: "test-webserver", + version: "1.0.0", + dependencies: { + express: "^4.18.0", + }, + }; + + const serverJs = ` +const express = require('express'); +const app = express(); +const port = 3000; + +app.get('/', (req, res) => { + res.json({ + message: 'Rivet test successful!', + timestamp: new Date().toISOString(), + hostname: require('os').hostname() + }); +}); + +app.get('/health', (req, res) => { + res.json({ status: 'healthy' }); +}); + +app.listen(port, '0.0.0.0', () => { + console.log(\`Test server listening on port \${port}\`); +}); +`; + + await mkdir(join(contextDir, "docker"), { recursive: true }); + await writeFile( + join(contextDir, "docker/app.dockerfile"), + dockerfile.trim(), + ); + await writeFile( + join(contextDir, "package.json"), + JSON.stringify(packageJson, null, 2), + ); + await writeFile(join(contextDir, "server.js"), serverJs.trim()); + + console.log(`Building test web server image: ${imageName}`); + execSync(`docker build -f docker/app.dockerfile -t ${imageName} .`, { + cwd: contextDir, + stdio: "pipe", + }); + + const dockerTarPath = `/tmp/webserver-image-${testId}.tar`; + console.log(`Saving Docker image to: ${dockerTarPath}`); + execSync(`docker save -o ${dockerTarPath} ${imageName}`, { + stdio: "pipe", + }); + + return { dockerTarPath, imageName }; +} + +export async function createTestWebServerContext(): Promise { + const testId = randomUUID(); + const tempDir = `/tmp/webserver-context-${testId}`; + await mkdir(tempDir, { recursive: true }); + await mkdir(join(tempDir, "configs"), { recursive: true }); + + const dockerfile = ` +FROM node:18-alpine +WORKDIR /app +COPY package.json server.js ./ +RUN npm install +EXPOSE 3000 +CMD ["node", "server.js"] +`; + + const packageJson = { + name: "test-webserver", + version: "1.0.0", + dependencies: { + express: "^4.18.0", + }, + }; + + const serverJs = ` +const express = require('express'); +const app = express(); +const port = 3000; + +app.get('/', (req, res) => { + res.json({ + message: 'Rivet test successful!', + timestamp: new Date().toISOString(), + hostname: require('os').hostname() + }); +}); + +app.get('/health', (req, res) => { + res.json({ status: 'healthy' }); +}); + +app.listen(port, '0.0.0.0', () => { + console.log(\`Test server listening on port \${port}\`); +}); +`; + + await writeFile( + join(tempDir, "configs/build.dockerfile"), + dockerfile.trim(), + ); + await writeFile( + join(tempDir, "package.json"), + JSON.stringify(packageJson, null, 2), + ); + await writeFile(join(tempDir, "server.js"), serverJs.trim()); + + const tarPath = `/tmp/webserver-context-${testId}.tar.gz`; + + await tar.create( + { + gzip: true, + file: tarPath, + cwd: tempDir, + }, + ["."], + ); + + const fileBuffer = await readFile(tarPath); + return fileBuffer; +} + +export async function downloadOutputTar( + serverUrl: string, + buildId: string, +): Promise { + const response = await fetch( + `${serverUrl}/builds/${buildId}/output.tar.gz`, + ); + + if (!response.ok) { + throw new Error(`Failed to download output: ${response.statusText}`); + } + + const arrayBuffer = await response.arrayBuffer(); + return Buffer.from(arrayBuffer); +} + +export async function pollBuildStatus( + baseUrl: string, + buildId?: string, +): Promise<{ status: string; buildId: string }> { + const maxAttempts = 150; + const interval = 2000; + + for (let attempt = 0; attempt < maxAttempts; attempt++) { + try { + const response = await fetch(`${baseUrl}/builds/${buildId}`); + if (!response.ok) { + throw new Error(`HTTP ${response.status}`); + } + + const build = await response.json(); + console.log( + `[${buildId}] Status: ${build.status.type} ${JSON.stringify(build.status.data)}`, + ); + + if ( + build.status.type === "success" || + build.status.type === "failure" + ) { + return { status: build.status.type, buildId: build.status.data?.buildId }; + } + + if (attempt < maxAttempts - 1) { + await new Promise((resolve) => setTimeout(resolve, interval)); + } + } catch (error) { + console.log( + `[${buildId}] Poll attempt ${attempt + 1} failed:`, + error, + ); + if (attempt < maxAttempts - 1) { + await new Promise((resolve) => setTimeout(resolve, interval)); + } + } + } + + throw new Error(`Build polling timeout after ${maxAttempts} attempts`); +} + +export async function createBuildWithContext( + baseUrl: string, + buildName: string, + dockerfilePath: string, + contextBuffer: Buffer, + environmentId?: string, +): Promise { + const formData = new FormData(); + formData.append("buildName", buildName); + formData.append("dockerfilePath", dockerfilePath); + if (environmentId) { + formData.append("environmentId", environmentId); + } + formData.append( + "context", + new Blob([contextBuffer], { type: "application/gzip" }), + ); + + const response = await fetch(`${baseUrl}/builds`, { + method: "POST", + body: formData, + }); + + if (!response.ok) { + throw new Error(`Failed to create build: ${response.statusText}`); + } + + const result = await response.json(); + return result.buildId; +} + +export async function getBuildStatus( + baseUrl: string, + buildId: string, +): Promise { + const response = await fetch(`${baseUrl}/builds/${buildId}`); + return await response.json(); +} + + +export async function testActorEndpoint(endpoint: string): Promise { + const response = await fetch(`${endpoint}`, { + method: "GET", + headers: { "User-Agent": "rivet-test" }, + }); + + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`); + } + + return await response.json(); +} + +export async function createActorFromBuild( + buildId: string, + buildName: string, + rivetConfig: { token: string; project: string; environment: string }, +): Promise<{ actorId: string; endpoint: string }> { + const { RivetClient } = await import("@rivet-gg/api"); + const client = new RivetClient({ token: rivetConfig.token }); + + console.log(`Creating actor with build ${buildName} and ID ${buildId}...`); + const { actor } = await client.actors.create({ + project: rivetConfig.project, + environment: rivetConfig.environment, + body: { + tags: { name: buildName }, + build: buildId, + network: { + ports: { + http: { + protocol: "https", + internalPort: 3000, + }, + }, + }, + resources: { + cpu: 100, + memory: 128, + }, + }, + }); + + const endpoint = actor.network?.ports?.http?.url; + if (!endpoint) { + throw new Error("Actor endpoint not available"); + } + + return { + actorId: actor.id, + endpoint, + }; +} + +export async function waitForActorReady(endpoint: string): Promise { + const maxAttempts = 30; + const interval = 2000; + + for (let attempt = 0; attempt < maxAttempts; attempt++) { + try { + const response = await fetch(`${endpoint}/health`, { + method: "GET", + headers: { "User-Agent": "rivet-test" }, + }); + + if (response.ok) { + console.log("Actor is ready!"); + return; + } + } catch (error) { + console.log(`Waiting for actor to be ready... (attempt ${attempt + 1})`); + } + + if (attempt < maxAttempts - 1) { + await new Promise((resolve) => setTimeout(resolve, interval)); + } + } + + throw new Error(`Actor not ready after ${maxAttempts} attempts`); +} + diff --git a/cloud/packages/ci-manager/tests/upload-workflow.test.ts b/cloud/packages/ci-manager/tests/upload-workflow.test.ts new file mode 100644 index 0000000000..f1680517fe --- /dev/null +++ b/cloud/packages/ci-manager/tests/upload-workflow.test.ts @@ -0,0 +1,167 @@ +import { test, expect, beforeAll, afterAll } from "vitest"; +import { mkdir, rm } from "fs/promises"; +import { convertDockerTarToOCIBundle } from "../src/oci-converter"; +import { + uploadOCIBundleToRivet, + type RivetUploadConfig, +} from "../src/rivet-uploader"; +import { RivetClient } from "@rivet-gg/api"; +import { + createTestWebServerImage, + waitForActorReady, + testActorEndpoint, +} from "./test-utils"; + +const TEST_DIR = "/tmp/upload-test"; + +let rivetConfig: RivetUploadConfig; +let testActorIds: string[] = []; + +async function createRivetActor( + buildId: string, + buildName: string, + config: RivetUploadConfig, +): Promise<{ actorId: string; endpoint?: string }> { + const client = new RivetClient({ token: config.token }); + + try { + const response = await client.actors.create({ + project: config.project, + environment: config.environment, + body: { + tags: { name: buildName }, + buildTags: { + name: buildName, + current: "true", + }, + network: { + ports: { + http: { + protocol: "https", + internalPort: 3000, + }, + }, + }, + resources: { + cpu: 100, + memory: 128, + }, + }, + }); + + const actorId = response.actor.id; + + await new Promise((resolve) => setTimeout(resolve, 5000)); + + const actorDetails = await client.actors.get(actorId, { + project: config.project, + environment: config.environment, + }); + + const endpoint = actorDetails.actor.network?.ports?.http?.hostname; + + return { + actorId, + endpoint: endpoint ? `https://${endpoint}` : undefined, + }; + } catch (error) { + throw new Error(`Failed to create Rivet actor: ${error}`); + } +} + +async function destroyRivetActor( + actorId: string, + config: RivetUploadConfig, +): Promise { + const client = new RivetClient({ token: config.token }); + + try { + await client.actors.destroy(actorId, { + project: config.project, + environment: config.environment, + }); + + console.log(`Rivet actor destroyed: ${actorId}`); + } catch (error) { + throw new Error(`Failed to destroy Rivet actor: ${error}`); + } +} + +beforeAll(async () => { + await mkdir(TEST_DIR, { recursive: true }); + + const token = process.env.RIVET_CLOUD_TOKEN; + const project = process.env.RIVET_PROJECT; + const environment = process.env.RIVET_ENVIRONMENT; + + if (!token || !project || !environment) { + throw new Error( + "Missing required environment variables: RIVET_CLOUD_TOKEN, RIVET_PROJECT, RIVET_ENVIRONMENT", + ); + } + + rivetConfig = { token, project, environment: "staging" }; +}); + +afterAll(async () => { + for (const actorId of testActorIds) { + try { + await destroyRivetActor(actorId, rivetConfig); + console.log(`Cleaned up test actor: ${actorId}`); + } catch (error) { + console.warn(`Failed to cleanup test actor ${actorId}:`, error); + } + } + + await rm(TEST_DIR, { recursive: true, force: true }); +}); + +test("upload workflow", async () => { + const { dockerTarPath, imageName } = await createTestWebServerImage(); + const conversionResult = await convertDockerTarToOCIBundle(dockerTarPath); + + let actorId: string | undefined; + + try { + console.log("Uploading OCI bundle to Rivet..."); + const uploadResult = await uploadOCIBundleToRivet( + conversionResult.bundleTarPath, + "rivet-upload-test", + imageName, + rivetConfig, + "2.0.0", + ); + + console.log(`Build uploaded: ${uploadResult.buildId}`); + + console.log("Creating Rivet actor..."); + const actorResult = await createRivetActor( + uploadResult.buildId, + "rivet-upload-test", + rivetConfig, + ); + + actorId = actorResult.actorId; + testActorIds.push(actorId); + expect(actorResult.endpoint).toBeDefined(); + + console.log(`Actor created: ${actorId}`); + console.log(`Actor endpoint: ${actorResult.endpoint}`); + + await waitForActorReady(actorResult.endpoint!); + + console.log("Testing actor HTTP endpoint..."); + const response = await testActorEndpoint(actorResult.endpoint!); + + expect(response).toBeDefined(); + expect(response.message).toBe("Rivet test successful!"); + expect(response.timestamp).toBeDefined(); + expect(response.hostname).toBeDefined(); + + console.log("Actor HTTP test successful:", response); + + console.log("✅ Upload workflow test completed successfully"); + } finally { + await conversionResult.cleanup(); + } +}, 600000); \ No newline at end of file diff --git a/cloud/packages/ci-manager/tsconfig.json b/cloud/packages/ci-manager/tsconfig.json new file mode 100644 index 0000000000..195a99ceac --- /dev/null +++ b/cloud/packages/ci-manager/tsconfig.json @@ -0,0 +1,43 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "CommonJS", + "moduleResolution": "node", + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + "skipLibCheck": true, + "declaration": false, + "outDir": "./dist", + "rootDir": "./src", + "removeComments": true, + "isolatedModules": true, + "allowJs": true, + "checkJs": false, + "incremental": true, + "tsBuildInfoFile": "./dist/.tsbuildinfo", + "types": ["node"], + "lib": ["ES2022", "DOM"] + }, + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "node_modules", + "dist", + "**/*.test.ts", + "**/*.spec.ts" + ], + "ts-node": { + "esm": true, + "experimentalSpecifierResolution": "node" + } +} diff --git a/cloud/packages/ci-manager/yarn.lock b/cloud/packages/ci-manager/yarn.lock new file mode 100644 index 0000000000..2fba9a3a8d --- /dev/null +++ b/cloud/packages/ci-manager/yarn.lock @@ -0,0 +1,2351 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 8 + cacheKey: 10c0 + +"@esbuild/aix-ppc64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/aix-ppc64@npm:0.25.5" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-arm64@npm:0.25.5" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/android-arm@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-arm@npm:0.25.5" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@esbuild/android-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-x64@npm:0.25.5" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/darwin-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/darwin-arm64@npm:0.25.5" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/darwin-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/darwin-x64@npm:0.25.5" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/freebsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/freebsd-arm64@npm:0.25.5" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/freebsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/freebsd-x64@npm:0.25.5" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/linux-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-arm64@npm:0.25.5" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/linux-arm@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-arm@npm:0.25.5" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@esbuild/linux-ia32@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-ia32@npm:0.25.5" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/linux-loong64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-loong64@npm:0.25.5" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + +"@esbuild/linux-mips64el@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-mips64el@npm:0.25.5" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + +"@esbuild/linux-ppc64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-ppc64@npm:0.25.5" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/linux-riscv64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-riscv64@npm:0.25.5" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + +"@esbuild/linux-s390x@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-s390x@npm:0.25.5" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + +"@esbuild/linux-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-x64@npm:0.25.5" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/netbsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/netbsd-arm64@npm:0.25.5" + conditions: os=netbsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/netbsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/netbsd-x64@npm:0.25.5" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openbsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/openbsd-arm64@npm:0.25.5" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/openbsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/openbsd-x64@npm:0.25.5" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/sunos-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/sunos-x64@npm:0.25.5" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/win32-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-arm64@npm:0.25.5" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/win32-ia32@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-ia32@npm:0.25.5" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/win32-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-x64@npm:0.25.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@hono/node-server@npm:^1.14.4": + version: 1.14.4 + resolution: "@hono/node-server@npm:1.14.4" + peerDependencies: + hono: ^4 + checksum: 10c0/1dc6296ddda0b9708cbafb406e22fb3d937505b80ec991483a5066ffa162da2cb2331b4591e7b4bbc07c62e2bea7b3a751cb0fcff33f9fba870ff95a694261ef + languageName: node + linkType: hard + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: "npm:^5.1.2" + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: "npm:^7.0.1" + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: "npm:^8.1.0" + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e + languageName: node + linkType: hard + +"@isaacs/fs-minipass@npm:^4.0.0": + version: 4.0.1 + resolution: "@isaacs/fs-minipass@npm:4.0.1" + dependencies: + minipass: "npm:^7.0.4" + checksum: 10c0/c25b6dc1598790d5b55c0947a9b7d111cfa92594db5296c3b907e2f533c033666f692a3939eadac17b1c7c40d362d0b0635dc874cbfe3e70db7c2b07cc97a5d2 + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.5.0": + version: 1.5.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" + checksum: 10c0/2eb864f276eb1096c3c11da3e9bb518f6d9fc0023c78344cdc037abadc725172c70314bdb360f2d4b7bffec7f5d657ce006816bc5d4ecb35e61b66132db00c18 + languageName: node + linkType: hard + +"@npmcli/agent@npm:^3.0.0": + version: 3.0.0 + resolution: "@npmcli/agent@npm:3.0.0" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.3" + checksum: 10c0/efe37b982f30740ee77696a80c196912c274ecd2cb243bc6ae7053a50c733ce0f6c09fda085145f33ecf453be19654acca74b69e81eaad4c90f00ccffe2f9271 + languageName: node + linkType: hard + +"@npmcli/fs@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/fs@npm:4.0.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 10c0/c90935d5ce670c87b6b14fab04a965a3b8137e585f8b2a6257263bd7f97756dd736cb165bb470e5156a9e718ecd99413dccc54b1138c1a46d6ec7cf325982fe5 + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd + languageName: node + linkType: hard + +"@rivet-gg/api@npm:^25.4.2": + version: 25.4.2 + resolution: "@rivet-gg/api@npm:25.4.2" + dependencies: + form-data: "npm:^4.0.0" + js-base64: "npm:^3.7.5" + node-fetch: "npm:2" + qs: "npm:^6.11.2" + readable-stream: "npm:^4.5.2" + url-join: "npm:^5.0.0" + checksum: 10c0/eb6a25b1468b9cd8f9b548fa7cdec948d8bcc21bc1274b06507b1b519cbba739cc828974a0917ebee9ab18c92ba7fe228d8ac596b3e71c5efaf4f4f8ed12c8f1 + languageName: node + linkType: hard + +"@rollup/rollup-android-arm-eabi@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.42.0" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@rollup/rollup-android-arm64@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-android-arm64@npm:4.42.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-arm64@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-darwin-arm64@npm:4.42.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-x64@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-darwin-x64@npm:4.42.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-freebsd-arm64@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.42.0" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-freebsd-x64@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-freebsd-x64@npm:4.42.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-gnueabihf@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.42.0" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-musleabihf@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.42.0" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-gnu@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.42.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-musl@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.42.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-loongarch64-gnu@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.42.0" + conditions: os=linux & cpu=loong64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.42.0" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.42.0" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-musl@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.42.0" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-s390x-gnu@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.42.0" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-gnu@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.42.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-musl@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.42.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-win32-arm64-msvc@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.42.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-win32-ia32-msvc@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.42.0" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@rollup/rollup-win32-x64-msvc@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.42.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@types/chai@npm:^5.2.2": + version: 5.2.2 + resolution: "@types/chai@npm:5.2.2" + dependencies: + "@types/deep-eql": "npm:*" + checksum: 10c0/49282bf0e8246800ebb36f17256f97bd3a8c4fb31f92ad3c0eaa7623518d7e87f1eaad4ad206960fcaf7175854bdff4cb167e4fe96811e0081b4ada83dd533ec + languageName: node + linkType: hard + +"@types/deep-eql@npm:*": + version: 4.0.2 + resolution: "@types/deep-eql@npm:4.0.2" + checksum: 10c0/bf3f811843117900d7084b9d0c852da9a044d12eb40e6de73b552598a6843c21291a8a381b0532644574beecd5e3491c5ff3a0365ab86b15d59862c025384844 + languageName: node + linkType: hard + +"@types/estree@npm:1.0.7": + version: 1.0.7 + resolution: "@types/estree@npm:1.0.7" + checksum: 10c0/be815254316882f7c40847336cd484c3bc1c3e34f710d197160d455dc9d6d050ffbf4c3bc76585dba86f737f020ab20bdb137ebe0e9116b0c86c7c0342221b8c + languageName: node + linkType: hard + +"@types/estree@npm:^1.0.0": + version: 1.0.8 + resolution: "@types/estree@npm:1.0.8" + checksum: 10c0/39d34d1afaa338ab9763f37ad6066e3f349444f9052b9676a7cc0252ef9485a41c6d81c9c4e0d26e9077993354edf25efc853f3224dd4b447175ef62bdcc86a5 + languageName: node + linkType: hard + +"@types/eventsource@npm:^1.1.15": + version: 1.1.15 + resolution: "@types/eventsource@npm:1.1.15" + checksum: 10c0/afee5c6c1185e365802349878411324569c77ae9878317b6e34bd633bdb5ee0a6eada6d1b358fec57640fe610eb43535344076db199895e1d9ab81511bb6ed0e + languageName: node + linkType: hard + +"@types/node@npm:^22.15.30": + version: 22.15.30 + resolution: "@types/node@npm:22.15.30" + dependencies: + undici-types: "npm:~6.21.0" + checksum: 10c0/ca330ac0e7fd502686d6df115fcc606aba46fd334220f749bbba2f639accdadcb23f7900603ceccdc8240be736739cad5c0b87c0fa92c9255a4dff245f07d664 + languageName: node + linkType: hard + +"@vitest/expect@npm:3.2.3": + version: 3.2.3 + resolution: "@vitest/expect@npm:3.2.3" + dependencies: + "@types/chai": "npm:^5.2.2" + "@vitest/spy": "npm:3.2.3" + "@vitest/utils": "npm:3.2.3" + chai: "npm:^5.2.0" + tinyrainbow: "npm:^2.0.0" + checksum: 10c0/5eb6278be8f5294779472d1276e150a1b573274441a68c2681c447179abd22af451813fdfbe87e04f5909ca7a0926700f9b79022f227c9816e5d0fa8e0229e15 + languageName: node + linkType: hard + +"@vitest/mocker@npm:3.2.3": + version: 3.2.3 + resolution: "@vitest/mocker@npm:3.2.3" + dependencies: + "@vitest/spy": "npm:3.2.3" + estree-walker: "npm:^3.0.3" + magic-string: "npm:^0.30.17" + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + checksum: 10c0/b670f229c3b1de5561de3cbbecb18f964d4888355d7f1cb8bbff4350b2cfbe477bef834cc2f66af7727ca7dc567540018885eb652f46e0be1cda4015491dc0a9 + languageName: node + linkType: hard + +"@vitest/pretty-format@npm:3.2.3, @vitest/pretty-format@npm:^3.2.3": + version: 3.2.3 + resolution: "@vitest/pretty-format@npm:3.2.3" + dependencies: + tinyrainbow: "npm:^2.0.0" + checksum: 10c0/e8fa7b97822c58404bef07d19fa9a49d5b7edb6797dd355584ad7246585bbbe9c55dd1fb05d0c3939b9c15fba05c3e134e2b96ea0cb64ca79a2b9dab60087a6a + languageName: node + linkType: hard + +"@vitest/runner@npm:3.2.3": + version: 3.2.3 + resolution: "@vitest/runner@npm:3.2.3" + dependencies: + "@vitest/utils": "npm:3.2.3" + pathe: "npm:^2.0.3" + strip-literal: "npm:^3.0.0" + checksum: 10c0/c20cb6e2ac4fdfb3d4f5136714ea65f9063562d3afaa1574dc82f53d061444bc01583f9915346768ca75f5ea0658f02fb594752e21abbca5ab50290f58732147 + languageName: node + linkType: hard + +"@vitest/snapshot@npm:3.2.3": + version: 3.2.3 + resolution: "@vitest/snapshot@npm:3.2.3" + dependencies: + "@vitest/pretty-format": "npm:3.2.3" + magic-string: "npm:^0.30.17" + pathe: "npm:^2.0.3" + checksum: 10c0/f6dd0248afb3f3cbcbbb9fd39c2c8273c4ec92176f65e6ba9d36a0c33552d3658013e3a02944e14c7637f51d6702a5c07963b59707ca459bd1ac31f39c81160c + languageName: node + linkType: hard + +"@vitest/spy@npm:3.2.3": + version: 3.2.3 + resolution: "@vitest/spy@npm:3.2.3" + dependencies: + tinyspy: "npm:^4.0.3" + checksum: 10c0/ce77d5934ac4741513993aad9d8ff44ff03ff5cf5a177e010c7ffcd8d3060087e56df1938c1100d49de712daf952cd2c72dd83e1684d043e698bd2afe0025f5e + languageName: node + linkType: hard + +"@vitest/utils@npm:3.2.3": + version: 3.2.3 + resolution: "@vitest/utils@npm:3.2.3" + dependencies: + "@vitest/pretty-format": "npm:3.2.3" + loupe: "npm:^3.1.3" + tinyrainbow: "npm:^2.0.0" + checksum: 10c0/c7a785a73bc0d7c0202ced0d9912639b9deb6f05dd6c25700a13d97e13320ccec57660f11ad1f9225419ac485339fdf7af28c8d77456bcb9558e6c7d73ad538a + languageName: node + linkType: hard + +"abbrev@npm:^3.0.0": + version: 3.0.1 + resolution: "abbrev@npm:3.0.1" + checksum: 10c0/21ba8f574ea57a3106d6d35623f2c4a9111d9ee3e9a5be47baed46ec2457d2eac46e07a5c4a60186f88cb98abbe3e24f2d4cca70bc2b12f1692523e2209a9ccf + languageName: node + linkType: hard + +"abort-controller@npm:^3.0.0": + version: 3.0.0 + resolution: "abort-controller@npm:3.0.0" + dependencies: + event-target-shim: "npm:^5.0.0" + checksum: 10c0/90ccc50f010250152509a344eb2e71977fbf8db0ab8f1061197e3275ddf6c61a41a6edfd7b9409c664513131dd96e962065415325ef23efa5db931b382d24ca5 + languageName: node + linkType: hard + +"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": + version: 7.1.3 + resolution: "agent-base@npm:7.1.3" + checksum: 10c0/6192b580c5b1d8fb399b9c62bf8343d76654c2dd62afcb9a52b2cf44a8b6ace1e3b704d3fe3547d91555c857d3df02603341ff2cb961b9cfe2b12f9f3c38ee11 + languageName: node + linkType: hard + +"ansi-regex@npm:^5.0.1": + version: 5.0.1 + resolution: "ansi-regex@npm:5.0.1" + checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 + languageName: node + linkType: hard + +"ansi-regex@npm:^6.0.1": + version: 6.1.0 + resolution: "ansi-regex@npm:6.1.0" + checksum: 10c0/a91daeddd54746338478eef88af3439a7edf30f8e23196e2d6ed182da9add559c601266dbef01c2efa46a958ad6f1f8b176799657616c702b5b02e799e7fd8dc + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: "npm:^2.0.1" + checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.1.0": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c + languageName: node + linkType: hard + +"assertion-error@npm:^2.0.1": + version: 2.0.1 + resolution: "assertion-error@npm:2.0.1" + checksum: 10c0/bbbcb117ac6480138f8c93cf7f535614282dea9dc828f540cdece85e3c665e8f78958b96afac52f29ff883c72638e6a87d469ecc9fe5bc902df03ed24a55dba8 + languageName: node + linkType: hard + +"asynckit@npm:^0.4.0": + version: 0.4.0 + resolution: "asynckit@npm:0.4.0" + checksum: 10c0/d73e2ddf20c4eb9337e1b3df1a0f6159481050a5de457c55b14ea2e5cb6d90bb69e004c9af54737a5ee0917fcf2c9e25de67777bbe58261847846066ba75bc9d + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee + languageName: node + linkType: hard + +"base64-js@npm:^1.3.1": + version: 1.5.1 + resolution: "base64-js@npm:1.5.1" + checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf + languageName: node + linkType: hard + +"brace-expansion@npm:^2.0.1": + version: 2.0.1 + resolution: "brace-expansion@npm:2.0.1" + dependencies: + balanced-match: "npm:^1.0.0" + checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f + languageName: node + linkType: hard + +"buffer@npm:^6.0.3": + version: 6.0.3 + resolution: "buffer@npm:6.0.3" + dependencies: + base64-js: "npm:^1.3.1" + ieee754: "npm:^1.2.1" + checksum: 10c0/2a905fbbcde73cc5d8bd18d1caa23715d5f83a5935867c2329f0ac06104204ba7947be098fe1317fbd8830e26090ff8e764f08cd14fefc977bb248c3487bcbd0 + languageName: node + linkType: hard + +"cac@npm:^6.7.14": + version: 6.7.14 + resolution: "cac@npm:6.7.14" + checksum: 10c0/4ee06aaa7bab8981f0d54e5f5f9d4adcd64058e9697563ce336d8a3878ed018ee18ebe5359b2430eceae87e0758e62ea2019c3f52ae6e211b1bd2e133856cd10 + languageName: node + linkType: hard + +"cacache@npm:^19.0.1": + version: 19.0.1 + resolution: "cacache@npm:19.0.1" + dependencies: + "@npmcli/fs": "npm:^4.0.0" + fs-minipass: "npm:^3.0.0" + glob: "npm:^10.2.2" + lru-cache: "npm:^10.0.1" + minipass: "npm:^7.0.3" + minipass-collect: "npm:^2.0.1" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + p-map: "npm:^7.0.2" + ssri: "npm:^12.0.0" + tar: "npm:^7.4.3" + unique-filename: "npm:^4.0.0" + checksum: 10c0/01f2134e1bd7d3ab68be851df96c8d63b492b1853b67f2eecb2c37bb682d37cb70bb858a16f2f0554d3c0071be6dfe21456a1ff6fa4b7eed996570d6a25ffe9c + languageName: node + linkType: hard + +"call-bind-apply-helpers@npm:^1.0.1, call-bind-apply-helpers@npm:^1.0.2": + version: 1.0.2 + resolution: "call-bind-apply-helpers@npm:1.0.2" + dependencies: + es-errors: "npm:^1.3.0" + function-bind: "npm:^1.1.2" + checksum: 10c0/47bd9901d57b857590431243fea704ff18078b16890a6b3e021e12d279bbf211d039155e27d7566b374d49ee1f8189344bac9833dec7a20cdec370506361c938 + languageName: node + linkType: hard + +"call-bound@npm:^1.0.2": + version: 1.0.4 + resolution: "call-bound@npm:1.0.4" + dependencies: + call-bind-apply-helpers: "npm:^1.0.2" + get-intrinsic: "npm:^1.3.0" + checksum: 10c0/f4796a6a0941e71c766aea672f63b72bc61234c4f4964dc6d7606e3664c307e7d77845328a8f3359ce39ddb377fed67318f9ee203dea1d47e46165dcf2917644 + languageName: node + linkType: hard + +"chai@npm:^5.2.0": + version: 5.2.0 + resolution: "chai@npm:5.2.0" + dependencies: + assertion-error: "npm:^2.0.1" + check-error: "npm:^2.1.1" + deep-eql: "npm:^5.0.1" + loupe: "npm:^3.1.0" + pathval: "npm:^2.0.0" + checksum: 10c0/dfd1cb719c7cebb051b727672d382a35338af1470065cb12adb01f4ee451bbf528e0e0f9ab2016af5fc1eea4df6e7f4504dc8443f8f00bd8fb87ad32dc516f7d + languageName: node + linkType: hard + +"check-error@npm:^2.1.1": + version: 2.1.1 + resolution: "check-error@npm:2.1.1" + checksum: 10c0/979f13eccab306cf1785fa10941a590b4e7ea9916ea2a4f8c87f0316fc3eab07eabefb6e587424ef0f88cbcd3805791f172ea739863ca3d7ce2afc54641c7f0e + languageName: node + linkType: hard + +"chownr@npm:^3.0.0": + version: 3.0.0 + resolution: "chownr@npm:3.0.0" + checksum: 10c0/43925b87700f7e3893296c8e9c56cc58f926411cce3a6e5898136daaf08f08b9a8eb76d37d3267e707d0dcc17aed2e2ebdf5848c0c3ce95cf910a919935c1b10 + languageName: node + linkType: hard + +"ci-manager@workspace:.": + version: 0.0.0-use.local + resolution: "ci-manager@workspace:." + dependencies: + "@hono/node-server": "npm:^1.14.4" + "@rivet-gg/api": "npm:^25.4.2" + "@types/eventsource": "npm:^1.1.15" + "@types/node": "npm:^22.15.30" + eventsource: "npm:^4.0.0" + get-port: "npm:^7.1.0" + hono: "npm:^4.7.11" + nanoevents: "npm:^9.1.0" + tar: "npm:^7.4.3" + tsx: "npm:^4.19.4" + typescript: "npm:^5.7.2" + vitest: "npm:^3.2.2" + zod: "npm:^3.25.56" + zx: "npm:^8.1.9" + peerDependencies: + typescript: ^5 + languageName: unknown + linkType: soft + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: "npm:~1.1.4" + checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 + languageName: node + linkType: hard + +"color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 + languageName: node + linkType: hard + +"combined-stream@npm:^1.0.8": + version: 1.0.8 + resolution: "combined-stream@npm:1.0.8" + dependencies: + delayed-stream: "npm:~1.0.0" + checksum: 10c0/0dbb829577e1b1e839fa82b40c07ffaf7de8a09b935cadd355a73652ae70a88b4320db322f6634a4ad93424292fa80973ac6480986247f1734a1137debf271d5 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.6": + version: 7.0.6 + resolution: "cross-spawn@npm:7.0.6" + dependencies: + path-key: "npm:^3.1.0" + shebang-command: "npm:^2.0.0" + which: "npm:^2.0.1" + checksum: 10c0/053ea8b2135caff68a9e81470e845613e374e7309a47731e81639de3eaeb90c3d01af0e0b44d2ab9d50b43467223b88567dfeb3262db942dc063b9976718ffc1 + languageName: node + linkType: hard + +"debug@npm:4, debug@npm:^4.3.4, debug@npm:^4.4.1": + version: 4.4.1 + resolution: "debug@npm:4.4.1" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/d2b44bc1afd912b49bb7ebb0d50a860dc93a4dd7d946e8de94abc957bb63726b7dd5aa48c18c2386c379ec024c46692e15ed3ed97d481729f929201e671fcd55 + languageName: node + linkType: hard + +"deep-eql@npm:^5.0.1": + version: 5.0.2 + resolution: "deep-eql@npm:5.0.2" + checksum: 10c0/7102cf3b7bb719c6b9c0db2e19bf0aa9318d141581befe8c7ce8ccd39af9eaa4346e5e05adef7f9bd7015da0f13a3a25dcfe306ef79dc8668aedbecb658dd247 + languageName: node + linkType: hard + +"delayed-stream@npm:~1.0.0": + version: 1.0.0 + resolution: "delayed-stream@npm:1.0.0" + checksum: 10c0/d758899da03392e6712f042bec80aa293bbe9e9ff1b2634baae6a360113e708b91326594c8a486d475c69d6259afb7efacdc3537bfcda1c6c648e390ce601b19 + languageName: node + linkType: hard + +"dunder-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "dunder-proto@npm:1.0.1" + dependencies: + call-bind-apply-helpers: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + gopd: "npm:^1.2.0" + checksum: 10c0/199f2a0c1c16593ca0a145dbf76a962f8033ce3129f01284d48c45ed4e14fea9bbacd7b3610b6cdc33486cef20385ac054948fefc6272fcce645c09468f93031 + languageName: node + linkType: hard + +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: "npm:^0.6.2" + checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 + languageName: node + linkType: hard + +"es-define-property@npm:^1.0.1": + version: 1.0.1 + resolution: "es-define-property@npm:1.0.1" + checksum: 10c0/3f54eb49c16c18707949ff25a1456728c883e81259f045003499efba399c08bad00deebf65cccde8c0e07908c1a225c9d472b7107e558f2a48e28d530e34527c + languageName: node + linkType: hard + +"es-errors@npm:^1.3.0": + version: 1.3.0 + resolution: "es-errors@npm:1.3.0" + checksum: 10c0/0a61325670072f98d8ae3b914edab3559b6caa980f08054a3b872052640d91da01d38df55df797fcc916389d77fc92b8d5906cf028f4db46d7e3003abecbca85 + languageName: node + linkType: hard + +"es-module-lexer@npm:^1.7.0": + version: 1.7.0 + resolution: "es-module-lexer@npm:1.7.0" + checksum: 10c0/4c935affcbfeba7fb4533e1da10fa8568043df1e3574b869385980de9e2d475ddc36769891936dbb07036edb3c3786a8b78ccf44964cd130dedc1f2c984b6c7b + languageName: node + linkType: hard + +"es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": + version: 1.1.1 + resolution: "es-object-atoms@npm:1.1.1" + dependencies: + es-errors: "npm:^1.3.0" + checksum: 10c0/65364812ca4daf48eb76e2a3b7a89b3f6a2e62a1c420766ce9f692665a29d94fe41fe88b65f24106f449859549711e4b40d9fb8002d862dfd7eb1c512d10be0c + languageName: node + linkType: hard + +"es-set-tostringtag@npm:^2.1.0": + version: 2.1.0 + resolution: "es-set-tostringtag@npm:2.1.0" + dependencies: + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.6" + has-tostringtag: "npm:^1.0.2" + hasown: "npm:^2.0.2" + checksum: 10c0/ef2ca9ce49afe3931cb32e35da4dcb6d86ab02592cfc2ce3e49ced199d9d0bb5085fc7e73e06312213765f5efa47cc1df553a6a5154584b21448e9fb8355b1af + languageName: node + linkType: hard + +"esbuild@npm:^0.25.0, esbuild@npm:~0.25.0": + version: 0.25.5 + resolution: "esbuild@npm:0.25.5" + dependencies: + "@esbuild/aix-ppc64": "npm:0.25.5" + "@esbuild/android-arm": "npm:0.25.5" + "@esbuild/android-arm64": "npm:0.25.5" + "@esbuild/android-x64": "npm:0.25.5" + "@esbuild/darwin-arm64": "npm:0.25.5" + "@esbuild/darwin-x64": "npm:0.25.5" + "@esbuild/freebsd-arm64": "npm:0.25.5" + "@esbuild/freebsd-x64": "npm:0.25.5" + "@esbuild/linux-arm": "npm:0.25.5" + "@esbuild/linux-arm64": "npm:0.25.5" + "@esbuild/linux-ia32": "npm:0.25.5" + "@esbuild/linux-loong64": "npm:0.25.5" + "@esbuild/linux-mips64el": "npm:0.25.5" + "@esbuild/linux-ppc64": "npm:0.25.5" + "@esbuild/linux-riscv64": "npm:0.25.5" + "@esbuild/linux-s390x": "npm:0.25.5" + "@esbuild/linux-x64": "npm:0.25.5" + "@esbuild/netbsd-arm64": "npm:0.25.5" + "@esbuild/netbsd-x64": "npm:0.25.5" + "@esbuild/openbsd-arm64": "npm:0.25.5" + "@esbuild/openbsd-x64": "npm:0.25.5" + "@esbuild/sunos-x64": "npm:0.25.5" + "@esbuild/win32-arm64": "npm:0.25.5" + "@esbuild/win32-ia32": "npm:0.25.5" + "@esbuild/win32-x64": "npm:0.25.5" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-arm64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-arm64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10c0/aba8cbc11927fa77562722ed5e95541ce2853f67ad7bdc40382b558abc2e0ec57d92ffb820f082ba2047b4ef9f3bc3da068cdebe30dfd3850cfa3827a78d604e + languageName: node + linkType: hard + +"estree-walker@npm:^3.0.3": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": "npm:^1.0.0" + checksum: 10c0/c12e3c2b2642d2bcae7d5aa495c60fa2f299160946535763969a1c83fc74518ffa9c2cd3a8b69ac56aea547df6a8aac25f729a342992ef0bbac5f1c73e78995d + languageName: node + linkType: hard + +"event-target-shim@npm:^5.0.0": + version: 5.0.1 + resolution: "event-target-shim@npm:5.0.1" + checksum: 10c0/0255d9f936215fd206156fd4caa9e8d35e62075d720dc7d847e89b417e5e62cf1ce6c9b4e0a1633a9256de0efefaf9f8d26924b1f3c8620cffb9db78e7d3076b + languageName: node + linkType: hard + +"events@npm:^3.3.0": + version: 3.3.0 + resolution: "events@npm:3.3.0" + checksum: 10c0/d6b6f2adbccbcda74ddbab52ed07db727ef52e31a61ed26db9feb7dc62af7fc8e060defa65e5f8af9449b86b52cc1a1f6a79f2eafcf4e62add2b7a1fa4a432f6 + languageName: node + linkType: hard + +"eventsource-parser@npm:^3.0.1": + version: 3.0.2 + resolution: "eventsource-parser@npm:3.0.2" + checksum: 10c0/067c6e60b7c68a4577630cc7e11d2aaeef52005e377a213308c7c2350596a175d5a179671d85f570726dce3f451c15d174ece4479ce68a1805686c88950d08dd + languageName: node + linkType: hard + +"eventsource@npm:^4.0.0": + version: 4.0.0 + resolution: "eventsource@npm:4.0.0" + dependencies: + eventsource-parser: "npm:^3.0.1" + checksum: 10c0/908a3f64b60aadd053b9fd8ea8b6a896a4faf32dbbaf0150e91abbec179a9e2a3da261fb577ae296df8b744de91962d69a60b10e8d7092d7802e6e3e7a8b0f0e + languageName: node + linkType: hard + +"expect-type@npm:^1.2.1": + version: 1.2.1 + resolution: "expect-type@npm:1.2.1" + checksum: 10c0/b775c9adab3c190dd0d398c722531726cdd6022849b4adba19dceab58dda7e000a7c6c872408cd73d665baa20d381eca36af4f7b393a4ba60dd10232d1fb8898 + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.2 + resolution: "exponential-backoff@npm:3.1.2" + checksum: 10c0/d9d3e1eafa21b78464297df91f1776f7fbaa3d5e3f7f0995648ca5b89c069d17055033817348d9f4a43d1c20b0eab84f75af6991751e839df53e4dfd6f22e844 + languageName: node + linkType: hard + +"fdir@npm:^6.4.4": + version: 6.4.5 + resolution: "fdir@npm:6.4.5" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10c0/5d63330a1b97165e9b0fb20369fafc7cf826bc4b3e374efcb650bc77d7145ac01193b5da1a7591eab89ae6fd6b15cdd414085910b2a2b42296b1480c9f2677af + languageName: node + linkType: hard + +"foreground-child@npm:^3.1.0": + version: 3.3.1 + resolution: "foreground-child@npm:3.3.1" + dependencies: + cross-spawn: "npm:^7.0.6" + signal-exit: "npm:^4.0.1" + checksum: 10c0/8986e4af2430896e65bc2788d6679067294d6aee9545daefc84923a0a4b399ad9c7a3ea7bd8c0b2b80fdf4a92de4c69df3f628233ff3224260e9c1541a9e9ed3 + languageName: node + linkType: hard + +"form-data@npm:^4.0.0": + version: 4.0.3 + resolution: "form-data@npm:4.0.3" + dependencies: + asynckit: "npm:^0.4.0" + combined-stream: "npm:^1.0.8" + es-set-tostringtag: "npm:^2.1.0" + hasown: "npm:^2.0.2" + mime-types: "npm:^2.1.12" + checksum: 10c0/f0cf45873d600110b5fadf5804478377694f73a1ed97aaa370a74c90cebd7fe6e845a081171668a5476477d0d55a73a4e03d6682968fa8661eac2a81d651fcdb + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 + languageName: node + linkType: hard + +"fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: "npm:latest" + conditions: os=darwin + languageName: node + linkType: hard + +"function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 10c0/d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 + languageName: node + linkType: hard + +"get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": + version: 1.3.0 + resolution: "get-intrinsic@npm:1.3.0" + dependencies: + call-bind-apply-helpers: "npm:^1.0.2" + es-define-property: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.1.1" + function-bind: "npm:^1.1.2" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + hasown: "npm:^2.0.2" + math-intrinsics: "npm:^1.1.0" + checksum: 10c0/52c81808af9a8130f581e6a6a83e1ba4a9f703359e7a438d1369a5267a25412322f03dcbd7c549edaef0b6214a0630a28511d7df0130c93cfd380f4fa0b5b66a + languageName: node + linkType: hard + +"get-port@npm:^7.1.0": + version: 7.1.0 + resolution: "get-port@npm:7.1.0" + checksum: 10c0/896051fea0fd3df58c050566754ab91f46406e898ce0c708414739d908a5ac03ffef3eca7a494ea9cc1914439e8caccd2218010d1eeabdde914b9ff920fa28fc + languageName: node + linkType: hard + +"get-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "get-proto@npm:1.0.1" + dependencies: + dunder-proto: "npm:^1.0.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10c0/9224acb44603c5526955e83510b9da41baf6ae73f7398875fba50edc5e944223a89c4a72b070fcd78beb5f7bdda58ecb6294adc28f7acfc0da05f76a2399643c + languageName: node + linkType: hard + +"get-tsconfig@npm:^4.7.5": + version: 4.10.1 + resolution: "get-tsconfig@npm:4.10.1" + dependencies: + resolve-pkg-maps: "npm:^1.0.0" + checksum: 10c0/7f8e3dabc6a49b747920a800fb88e1952fef871cdf51b79e98db48275a5de6cdaf499c55ee67df5fa6fe7ce65f0063e26de0f2e53049b408c585aa74d39ffa21 + languageName: node + linkType: hard + +"glob@npm:^10.2.2": + version: 10.4.5 + resolution: "glob@npm:10.4.5" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^3.1.2" + minimatch: "npm:^9.0.4" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^1.11.1" + bin: + glob: dist/esm/bin.mjs + checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e + languageName: node + linkType: hard + +"gopd@npm:^1.2.0": + version: 1.2.0 + resolution: "gopd@npm:1.2.0" + checksum: 10c0/50fff1e04ba2b7737c097358534eacadad1e68d24cccee3272e04e007bed008e68d2614f3987788428fd192a5ae3889d08fb2331417e4fc4a9ab366b2043cead + languageName: node + linkType: hard + +"graceful-fs@npm:^4.2.6": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 + languageName: node + linkType: hard + +"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": + version: 1.1.0 + resolution: "has-symbols@npm:1.1.0" + checksum: 10c0/dde0a734b17ae51e84b10986e651c664379018d10b91b6b0e9b293eddb32f0f069688c841fb40f19e9611546130153e0a2a48fd7f512891fb000ddfa36f5a20e + languageName: node + linkType: hard + +"has-tostringtag@npm:^1.0.2": + version: 1.0.2 + resolution: "has-tostringtag@npm:1.0.2" + dependencies: + has-symbols: "npm:^1.0.3" + checksum: 10c0/a8b166462192bafe3d9b6e420a1d581d93dd867adb61be223a17a8d6dad147aa77a8be32c961bb2f27b3ef893cae8d36f564ab651f5e9b7938ae86f74027c48c + languageName: node + linkType: hard + +"hasown@npm:^2.0.2": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" + dependencies: + function-bind: "npm:^1.1.2" + checksum: 10c0/3769d434703b8ac66b209a4cca0737519925bbdb61dd887f93a16372b14694c63ff4e797686d87c90f08168e81082248b9b028bad60d4da9e0d1148766f56eb9 + languageName: node + linkType: hard + +"hono@npm:^4.7.11": + version: 4.7.11 + resolution: "hono@npm:4.7.11" + checksum: 10c0/2821471b09f2e9f7bab5ad7412e2e44df5f07b7098508d70dd6e368b933580f03a06c30e20dd764b53e0121e1b1ff2132ae98cffa7fd1b286e299f9054effd6a + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.1": + version: 4.2.0 + resolution: "http-cache-semantics@npm:4.2.0" + checksum: 10c0/45b66a945cf13ec2d1f29432277201313babf4a01d9e52f44b31ca923434083afeca03f18417f599c9ab3d0e7b618ceb21257542338b57c54b710463b4a53e37 + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" + dependencies: + agent-base: "npm:^7.1.0" + debug: "npm:^4.3.4" + checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^7.0.1": + version: 7.0.6 + resolution: "https-proxy-agent@npm:7.0.6" + dependencies: + agent-base: "npm:^7.1.2" + debug: "npm:4" + checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 + languageName: node + linkType: hard + +"ieee754@npm:^1.2.1": + version: 1.2.1 + resolution: "ieee754@npm:1.2.1" + checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 + languageName: node + linkType: hard + +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: "npm:1.1.0" + sprintf-js: "npm:^1.1.3" + checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d + languageName: node + linkType: hard + +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 + languageName: node + linkType: hard + +"jackspeak@npm:^3.1.2": + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 + languageName: node + linkType: hard + +"js-base64@npm:^3.7.5": + version: 3.7.7 + resolution: "js-base64@npm:3.7.7" + checksum: 10c0/3c905a7e78b601e4751b5e710edd0d6d045ce2d23eb84c9df03515371e1b291edc72808dc91e081cb9855aef6758292a2407006f4608ec3705373dd8baf2f80f + languageName: node + linkType: hard + +"js-tokens@npm:^9.0.1": + version: 9.0.1 + resolution: "js-tokens@npm:9.0.1" + checksum: 10c0/68dcab8f233dde211a6b5fd98079783cbcd04b53617c1250e3553ee16ab3e6134f5e65478e41d82f6d351a052a63d71024553933808570f04dbf828d7921e80e + languageName: node + linkType: hard + +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 + languageName: node + linkType: hard + +"loupe@npm:^3.1.0, loupe@npm:^3.1.3": + version: 3.1.3 + resolution: "loupe@npm:3.1.3" + checksum: 10c0/f5dab4144254677de83a35285be1b8aba58b3861439ce4ba65875d0d5f3445a4a496daef63100ccf02b2dbc25bf58c6db84c9cb0b96d6435331e9d0a33b48541 + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.4.3 + resolution: "lru-cache@npm:10.4.3" + checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb + languageName: node + linkType: hard + +"magic-string@npm:^0.30.17": + version: 0.30.17 + resolution: "magic-string@npm:0.30.17" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.0" + checksum: 10c0/16826e415d04b88378f200fe022b53e638e3838b9e496edda6c0e086d7753a44a6ed187adc72d19f3623810589bf139af1a315541cd6a26ae0771a0193eaf7b8 + languageName: node + linkType: hard + +"make-fetch-happen@npm:^14.0.3": + version: 14.0.3 + resolution: "make-fetch-happen@npm:14.0.3" + dependencies: + "@npmcli/agent": "npm:^3.0.0" + cacache: "npm:^19.0.1" + http-cache-semantics: "npm:^4.1.1" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^4.0.0" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + negotiator: "npm:^1.0.0" + proc-log: "npm:^5.0.0" + promise-retry: "npm:^2.0.1" + ssri: "npm:^12.0.0" + checksum: 10c0/c40efb5e5296e7feb8e37155bde8eb70bc57d731b1f7d90e35a092fde403d7697c56fb49334d92d330d6f1ca29a98142036d6480a12681133a0a1453164cb2f0 + languageName: node + linkType: hard + +"math-intrinsics@npm:^1.1.0": + version: 1.1.0 + resolution: "math-intrinsics@npm:1.1.0" + checksum: 10c0/7579ff94e899e2f76ab64491d76cf606274c874d8f2af4a442c016bd85688927fcfca157ba6bf74b08e9439dc010b248ce05b96cc7c126a354c3bae7fcb48b7f + languageName: node + linkType: hard + +"mime-db@npm:1.52.0": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 10c0/0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa + languageName: node + linkType: hard + +"mime-types@npm:^2.1.12": + version: 2.1.35 + resolution: "mime-types@npm:2.1.35" + dependencies: + mime-db: "npm:1.52.0" + checksum: 10c0/82fb07ec56d8ff1fc999a84f2f217aa46cb6ed1033fefaabd5785b9a974ed225c90dc72fff460259e66b95b73648596dbcc50d51ed69cdf464af2d237d3149b2 + languageName: node + linkType: hard + +"minimatch@npm:^9.0.4": + version: 9.0.5 + resolution: "minimatch@npm:9.0.5" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed + languageName: node + linkType: hard + +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e + languageName: node + linkType: hard + +"minipass-fetch@npm:^4.0.0": + version: 4.0.1 + resolution: "minipass-fetch@npm:4.0.1" + dependencies: + encoding: "npm:^0.1.13" + minipass: "npm:^7.0.3" + minipass-sized: "npm:^1.0.3" + minizlib: "npm:^3.0.1" + dependenciesMeta: + encoding: + optional: true + checksum: 10c0/a3147b2efe8e078c9bf9d024a0059339c5a09c5b1dded6900a219c218cc8b1b78510b62dae556b507304af226b18c3f1aeb1d48660283602d5b6586c399eed5c + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb + languageName: node + linkType: hard + +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: "npm:^4.0.0" + checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c + languageName: node + linkType: hard + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 + languageName: node + linkType: hard + +"minizlib@npm:^3.0.1": + version: 3.0.2 + resolution: "minizlib@npm:3.0.2" + dependencies: + minipass: "npm:^7.1.2" + checksum: 10c0/9f3bd35e41d40d02469cb30470c55ccc21cae0db40e08d1d0b1dff01cc8cc89a6f78e9c5d2b7c844e485ec0a8abc2238111213fdc5b2038e6d1012eacf316f78 + languageName: node + linkType: hard + +"mkdirp@npm:^3.0.1": + version: 3.0.1 + resolution: "mkdirp@npm:3.0.1" + bin: + mkdirp: dist/cjs/src/bin.js + checksum: 10c0/9f2b975e9246351f5e3a40dcfac99fcd0baa31fbfab615fe059fb11e51f10e4803c63de1f384c54d656e4db31d000e4767e9ef076a22e12a641357602e31d57d + languageName: node + linkType: hard + +"ms@npm:^2.1.3": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 + languageName: node + linkType: hard + +"nanoevents@npm:^9.1.0": + version: 9.1.0 + resolution: "nanoevents@npm:9.1.0" + checksum: 10c0/5fb48e6fc1d3102daddaeffd6eada907c25b1c8554dcc648e9cb0a72979a1ab3ee56ffa2d2b3e566a8e561a9e2992a3783493c61cfaaa096b2986d56dbbc1ca5 + languageName: node + linkType: hard + +"nanoid@npm:^3.3.11": + version: 3.3.11 + resolution: "nanoid@npm:3.3.11" + bin: + nanoid: bin/nanoid.cjs + checksum: 10c0/40e7f70b3d15f725ca072dfc4f74e81fcf1fbb02e491cf58ac0c79093adc9b0a73b152bcde57df4b79cd097e13023d7504acb38404a4da7bc1cd8e887b82fe0b + languageName: node + linkType: hard + +"negotiator@npm:^1.0.0": + version: 1.0.0 + resolution: "negotiator@npm:1.0.0" + checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b + languageName: node + linkType: hard + +"node-fetch@npm:2": + version: 2.7.0 + resolution: "node-fetch@npm:2.7.0" + dependencies: + whatwg-url: "npm:^5.0.0" + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8 + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 11.2.0 + resolution: "node-gyp@npm:11.2.0" + dependencies: + env-paths: "npm:^2.2.0" + exponential-backoff: "npm:^3.1.1" + graceful-fs: "npm:^4.2.6" + make-fetch-happen: "npm:^14.0.3" + nopt: "npm:^8.0.0" + proc-log: "npm:^5.0.0" + semver: "npm:^7.3.5" + tar: "npm:^7.4.3" + tinyglobby: "npm:^0.2.12" + which: "npm:^5.0.0" + bin: + node-gyp: bin/node-gyp.js + checksum: 10c0/bd8d8c76b06be761239b0c8680f655f6a6e90b48e44d43415b11c16f7e8c15be346fba0cbf71588c7cdfb52c419d928a7d3db353afc1d952d19756237d8f10b9 + languageName: node + linkType: hard + +"nopt@npm:^8.0.0": + version: 8.1.0 + resolution: "nopt@npm:8.1.0" + dependencies: + abbrev: "npm:^3.0.0" + bin: + nopt: bin/nopt.js + checksum: 10c0/62e9ea70c7a3eb91d162d2c706b6606c041e4e7b547cbbb48f8b3695af457dd6479904d7ace600856bf923dd8d1ed0696f06195c8c20f02ac87c1da0e1d315ef + languageName: node + linkType: hard + +"object-inspect@npm:^1.13.3": + version: 1.13.4 + resolution: "object-inspect@npm:1.13.4" + checksum: 10c0/d7f8711e803b96ea3191c745d6f8056ce1f2496e530e6a19a0e92d89b0fa3c76d910c31f0aa270432db6bd3b2f85500a376a83aaba849a8d518c8845b3211692 + languageName: node + linkType: hard + +"p-map@npm:^7.0.2": + version: 7.0.3 + resolution: "p-map@npm:7.0.3" + checksum: 10c0/46091610da2b38ce47bcd1d8b4835a6fa4e832848a6682cf1652bc93915770f4617afc844c10a77d1b3e56d2472bb2d5622353fa3ead01a7f42b04fc8e744a5c + languageName: node + linkType: hard + +"package-json-from-dist@npm:^1.0.0": + version: 1.0.1 + resolution: "package-json-from-dist@npm:1.0.1" + checksum: 10c0/62ba2785eb655fec084a257af34dbe24292ab74516d6aecef97ef72d4897310bc6898f6c85b5cd22770eaa1ce60d55a0230e150fb6a966e3ecd6c511e23d164b + languageName: node + linkType: hard + +"path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c + languageName: node + linkType: hard + +"path-scurry@npm:^1.11.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" + dependencies: + lru-cache: "npm:^10.2.0" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d + languageName: node + linkType: hard + +"pathe@npm:^2.0.3": + version: 2.0.3 + resolution: "pathe@npm:2.0.3" + checksum: 10c0/c118dc5a8b5c4166011b2b70608762e260085180bb9e33e80a50dcdb1e78c010b1624f4280c492c92b05fc276715a4c357d1f9edc570f8f1b3d90b6839ebaca1 + languageName: node + linkType: hard + +"pathval@npm:^2.0.0": + version: 2.0.0 + resolution: "pathval@npm:2.0.0" + checksum: 10c0/602e4ee347fba8a599115af2ccd8179836a63c925c23e04bd056d0674a64b39e3a081b643cc7bc0b84390517df2d800a46fcc5598d42c155fe4977095c2f77c5 + languageName: node + linkType: hard + +"picocolors@npm:^1.1.1": + version: 1.1.1 + resolution: "picocolors@npm:1.1.1" + checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 + languageName: node + linkType: hard + +"picomatch@npm:^4.0.2": + version: 4.0.2 + resolution: "picomatch@npm:4.0.2" + checksum: 10c0/7c51f3ad2bb42c776f49ebf964c644958158be30d0a510efd5a395e8d49cb5acfed5b82c0c5b365523ce18e6ab85013c9ebe574f60305892ec3fa8eee8304ccc + languageName: node + linkType: hard + +"postcss@npm:^8.5.3": + version: 8.5.4 + resolution: "postcss@npm:8.5.4" + dependencies: + nanoid: "npm:^3.3.11" + picocolors: "npm:^1.1.1" + source-map-js: "npm:^1.2.1" + checksum: 10c0/0feff648614a834f7cd5396ea6b05b658ca0507e10a4eaad03b56c348f6aec93f42a885fc1b30522630c6a7e49ae53b38a061e3cba526f2d9857afbe095a22bb + languageName: node + linkType: hard + +"proc-log@npm:^5.0.0": + version: 5.0.0 + resolution: "proc-log@npm:5.0.0" + checksum: 10c0/bbe5edb944b0ad63387a1d5b1911ae93e05ce8d0f60de1035b218cdcceedfe39dbd2c697853355b70f1a090f8f58fe90da487c85216bf9671f9499d1a897e9e3 + languageName: node + linkType: hard + +"process@npm:^0.11.10": + version: 0.11.10 + resolution: "process@npm:0.11.10" + checksum: 10c0/40c3ce4b7e6d4b8c3355479df77aeed46f81b279818ccdc500124e6a5ab882c0cc81ff7ea16384873a95a74c4570b01b120f287abbdd4c877931460eca6084b3 + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: "npm:^2.0.2" + retry: "npm:^0.12.0" + checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 + languageName: node + linkType: hard + +"qs@npm:^6.11.2": + version: 6.14.0 + resolution: "qs@npm:6.14.0" + dependencies: + side-channel: "npm:^1.1.0" + checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c + languageName: node + linkType: hard + +"readable-stream@npm:^4.5.2": + version: 4.7.0 + resolution: "readable-stream@npm:4.7.0" + dependencies: + abort-controller: "npm:^3.0.0" + buffer: "npm:^6.0.3" + events: "npm:^3.3.0" + process: "npm:^0.11.10" + string_decoder: "npm:^1.3.0" + checksum: 10c0/fd86d068da21cfdb10f7a4479f2e47d9c0a9b0c862fc0c840a7e5360201580a55ac399c764b12a4f6fa291f8cee74d9c4b7562e0d53b3c4b2769f2c98155d957 + languageName: node + linkType: hard + +"resolve-pkg-maps@npm:^1.0.0": + version: 1.0.0 + resolution: "resolve-pkg-maps@npm:1.0.0" + checksum: 10c0/fb8f7bbe2ca281a73b7ef423a1cbc786fb244bd7a95cbe5c3fba25b27d327150beca8ba02f622baea65919a57e061eb5005204daa5f93ed590d9b77463a567ab + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe + languageName: node + linkType: hard + +"rollup@npm:^4.40.0": + version: 4.42.0 + resolution: "rollup@npm:4.42.0" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.42.0" + "@rollup/rollup-android-arm64": "npm:4.42.0" + "@rollup/rollup-darwin-arm64": "npm:4.42.0" + "@rollup/rollup-darwin-x64": "npm:4.42.0" + "@rollup/rollup-freebsd-arm64": "npm:4.42.0" + "@rollup/rollup-freebsd-x64": "npm:4.42.0" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.42.0" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.42.0" + "@rollup/rollup-linux-arm64-gnu": "npm:4.42.0" + "@rollup/rollup-linux-arm64-musl": "npm:4.42.0" + "@rollup/rollup-linux-loongarch64-gnu": "npm:4.42.0" + "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.42.0" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.42.0" + "@rollup/rollup-linux-riscv64-musl": "npm:4.42.0" + "@rollup/rollup-linux-s390x-gnu": "npm:4.42.0" + "@rollup/rollup-linux-x64-gnu": "npm:4.42.0" + "@rollup/rollup-linux-x64-musl": "npm:4.42.0" + "@rollup/rollup-win32-arm64-msvc": "npm:4.42.0" + "@rollup/rollup-win32-ia32-msvc": "npm:4.42.0" + "@rollup/rollup-win32-x64-msvc": "npm:4.42.0" + "@types/estree": "npm:1.0.7" + fsevents: "npm:~2.3.2" + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-freebsd-arm64": + optional: true + "@rollup/rollup-freebsd-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-loongarch64-gnu": + optional: true + "@rollup/rollup-linux-powerpc64le-gnu": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-riscv64-musl": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 10c0/160fdb0874af5f0f619987b4e9abb3b136fc154f759762bfde4d65d864d6d06594ae7d1d8e6d4558d1b8ef329aaa6a8de543e90feead3d872db15cf61f78426c + languageName: node + linkType: hard + +"safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 + languageName: node + linkType: hard + +"semver@npm:^7.3.5": + version: 7.7.2 + resolution: "semver@npm:7.7.2" + bin: + semver: bin/semver.js + checksum: 10c0/aca305edfbf2383c22571cb7714f48cadc7ac95371b4b52362fb8eeffdfbc0de0669368b82b2b15978f8848f01d7114da65697e56cd8c37b0dab8c58e543f9ea + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: "npm:^3.0.0" + checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 + languageName: node + linkType: hard + +"side-channel-list@npm:^1.0.0": + version: 1.0.0 + resolution: "side-channel-list@npm:1.0.0" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.3" + checksum: 10c0/644f4ac893456c9490ff388bf78aea9d333d5e5bfc64cfb84be8f04bf31ddc111a8d4b83b85d7e7e8a7b845bc185a9ad02c052d20e086983cf59f0be517d9b3d + languageName: node + linkType: hard + +"side-channel-map@npm:^1.0.1": + version: 1.0.1 + resolution: "side-channel-map@npm:1.0.1" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + checksum: 10c0/010584e6444dd8a20b85bc926d934424bd809e1a3af941cace229f7fdcb751aada0fb7164f60c2e22292b7fa3c0ff0bce237081fd4cdbc80de1dc68e95430672 + languageName: node + linkType: hard + +"side-channel-weakmap@npm:^1.0.2": + version: 1.0.2 + resolution: "side-channel-weakmap@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + side-channel-map: "npm:^1.0.1" + checksum: 10c0/71362709ac233e08807ccd980101c3e2d7efe849edc51455030327b059f6c4d292c237f94dc0685031dd11c07dd17a68afde235d6cf2102d949567f98ab58185 + languageName: node + linkType: hard + +"side-channel@npm:^1.1.0": + version: 1.1.0 + resolution: "side-channel@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.3" + side-channel-list: "npm:^1.0.0" + side-channel-map: "npm:^1.0.1" + side-channel-weakmap: "npm:^1.0.2" + checksum: 10c0/cb20dad41eb032e6c24c0982e1e5a24963a28aa6122b4f05b3f3d6bf8ae7fd5474ef382c8f54a6a3ab86e0cac4d41a23bd64ede3970e5bfb50326ba02a7996e6 + languageName: node + linkType: hard + +"siginfo@npm:^2.0.0": + version: 2.0.0 + resolution: "siginfo@npm:2.0.0" + checksum: 10c0/3def8f8e516fbb34cb6ae415b07ccc5d9c018d85b4b8611e3dc6f8be6d1899f693a4382913c9ed51a06babb5201639d76453ab297d1c54a456544acf5c892e34 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.5 + resolution: "socks-proxy-agent@npm:8.0.5" + dependencies: + agent-base: "npm:^7.1.2" + debug: "npm:^4.3.4" + socks: "npm:^2.8.3" + checksum: 10c0/5d2c6cecba6821389aabf18728325730504bf9bb1d9e342e7987a5d13badd7a98838cc9a55b8ed3cb866ad37cc23e1086f09c4d72d93105ce9dfe76330e9d2a6 + languageName: node + linkType: hard + +"socks@npm:^2.8.3": + version: 2.8.4 + resolution: "socks@npm:2.8.4" + dependencies: + ip-address: "npm:^9.0.5" + smart-buffer: "npm:^4.2.0" + checksum: 10c0/00c3271e233ccf1fb83a3dd2060b94cc37817e0f797a93c560b9a7a86c4a0ec2961fb31263bdd24a3c28945e24868b5f063cd98744171d9e942c513454b50ae5 + languageName: node + linkType: hard + +"source-map-js@npm:^1.2.1": + version: 1.2.1 + resolution: "source-map-js@npm:1.2.1" + checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf + languageName: node + linkType: hard + +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec + languageName: node + linkType: hard + +"ssri@npm:^12.0.0": + version: 12.0.0 + resolution: "ssri@npm:12.0.0" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/caddd5f544b2006e88fa6b0124d8d7b28208b83c72d7672d5ade44d794525d23b540f3396108c4eb9280dcb7c01f0bef50682f5b4b2c34291f7c5e211fd1417d + languageName: node + linkType: hard + +"stackback@npm:0.0.2": + version: 0.0.2 + resolution: "stackback@npm:0.0.2" + checksum: 10c0/89a1416668f950236dd5ac9f9a6b2588e1b9b62b1b6ad8dff1bfc5d1a15dbf0aafc9b52d2226d00c28dffff212da464eaeebfc6b7578b9d180cef3e3782c5983 + languageName: node + linkType: hard + +"std-env@npm:^3.9.0": + version: 3.9.0 + resolution: "std-env@npm:3.9.0" + checksum: 10c0/4a6f9218aef3f41046c3c7ecf1f98df00b30a07f4f35c6d47b28329bc2531eef820828951c7d7b39a1c5eb19ad8a46e3ddfc7deb28f0a2f3ceebee11bab7ba50 + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: "npm:^8.0.0" + is-fullwidth-code-point: "npm:^3.0.0" + strip-ansi: "npm:^6.0.1" + checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b + languageName: node + linkType: hard + +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: "npm:^0.2.0" + emoji-regex: "npm:^9.2.2" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca + languageName: node + linkType: hard + +"string_decoder@npm:^1.3.0": + version: 1.3.0 + resolution: "string_decoder@npm:1.3.0" + dependencies: + safe-buffer: "npm:~5.2.0" + checksum: 10c0/810614ddb030e271cd591935dcd5956b2410dd079d64ff92a1844d6b7588bf992b3e1b69b0f4d34a3e06e0bd73046ac646b5264c1987b20d0601f81ef35d731d + languageName: node + linkType: hard + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: "npm:^5.0.1" + checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1": + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" + dependencies: + ansi-regex: "npm:^6.0.1" + checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 + languageName: node + linkType: hard + +"strip-literal@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-literal@npm:3.0.0" + dependencies: + js-tokens: "npm:^9.0.1" + checksum: 10c0/d81657f84aba42d4bbaf2a677f7e7f34c1f3de5a6726db8bc1797f9c0b303ba54d4660383a74bde43df401cf37cce1dff2c842c55b077a4ceee11f9e31fba828 + languageName: node + linkType: hard + +"tar@npm:^7.4.3": + version: 7.4.3 + resolution: "tar@npm:7.4.3" + dependencies: + "@isaacs/fs-minipass": "npm:^4.0.0" + chownr: "npm:^3.0.0" + minipass: "npm:^7.1.2" + minizlib: "npm:^3.0.1" + mkdirp: "npm:^3.0.1" + yallist: "npm:^5.0.0" + checksum: 10c0/d4679609bb2a9b48eeaf84632b6d844128d2412b95b6de07d53d8ee8baf4ca0857c9331dfa510390a0727b550fd543d4d1a10995ad86cdf078423fbb8d99831d + languageName: node + linkType: hard + +"tinybench@npm:^2.9.0": + version: 2.9.0 + resolution: "tinybench@npm:2.9.0" + checksum: 10c0/c3500b0f60d2eb8db65250afe750b66d51623057ee88720b7f064894a6cb7eb93360ca824a60a31ab16dab30c7b1f06efe0795b352e37914a9d4bad86386a20c + languageName: node + linkType: hard + +"tinyexec@npm:^0.3.2": + version: 0.3.2 + resolution: "tinyexec@npm:0.3.2" + checksum: 10c0/3efbf791a911be0bf0821eab37a3445c2ba07acc1522b1fa84ae1e55f10425076f1290f680286345ed919549ad67527d07281f1c19d584df3b74326909eb1f90 + languageName: node + linkType: hard + +"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.14": + version: 0.2.14 + resolution: "tinyglobby@npm:0.2.14" + dependencies: + fdir: "npm:^6.4.4" + picomatch: "npm:^4.0.2" + checksum: 10c0/f789ed6c924287a9b7d3612056ed0cda67306cd2c80c249fd280cf1504742b12583a2089b61f4abbd24605f390809017240e250241f09938054c9b363e51c0a6 + languageName: node + linkType: hard + +"tinypool@npm:^1.1.0": + version: 1.1.0 + resolution: "tinypool@npm:1.1.0" + checksum: 10c0/deb6bde5e3d85d4ba043806c66f43fb5b649716312a47b52761a83668ffc71cd0ea4e24254c1b02a3702e5c27e02605f0189a1460f6284a5930a08bd0c06435c + languageName: node + linkType: hard + +"tinyrainbow@npm:^2.0.0": + version: 2.0.0 + resolution: "tinyrainbow@npm:2.0.0" + checksum: 10c0/c83c52bef4e0ae7fb8ec6a722f70b5b6fa8d8be1c85792e829f56c0e1be94ab70b293c032dc5048d4d37cfe678f1f5babb04bdc65fd123098800148ca989184f + languageName: node + linkType: hard + +"tinyspy@npm:^4.0.3": + version: 4.0.3 + resolution: "tinyspy@npm:4.0.3" + checksum: 10c0/0a92a18b5350945cc8a1da3a22c9ad9f4e2945df80aaa0c43e1b3a3cfb64d8501e607ebf0305e048e3c3d3e0e7f8eb10cea27dc17c21effb73e66c4a3be36373 + languageName: node + linkType: hard + +"tr46@npm:~0.0.3": + version: 0.0.3 + resolution: "tr46@npm:0.0.3" + checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11 + languageName: node + linkType: hard + +"tsx@npm:^4.19.4": + version: 4.19.4 + resolution: "tsx@npm:4.19.4" + dependencies: + esbuild: "npm:~0.25.0" + fsevents: "npm:~2.3.3" + get-tsconfig: "npm:^4.7.5" + dependenciesMeta: + fsevents: + optional: true + bin: + tsx: dist/cli.mjs + checksum: 10c0/f7b8d44362343fbde1f2ecc9832d243a450e1168dd09702a545ebe5f699aa6912e45b431a54b885466db414cceda48e5067b36d182027c43b2c02a4f99d8721e + languageName: node + linkType: hard + +"typescript@npm:^5.7.2": + version: 5.8.3 + resolution: "typescript@npm:5.8.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/5f8bb01196e542e64d44db3d16ee0e4063ce4f3e3966df6005f2588e86d91c03e1fb131c2581baf0fb65ee79669eea6e161cd448178986587e9f6844446dbb48 + languageName: node + linkType: hard + +"typescript@patch:typescript@npm%3A^5.7.2#optional!builtin": + version: 5.8.3 + resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/39117e346ff8ebd87ae1510b3a77d5d92dae5a89bde588c747d25da5c146603a99c8ee588c7ef80faaf123d89ed46f6dbd918d534d641083177d5fac38b8a1cb + languageName: node + linkType: hard + +"undici-types@npm:~6.21.0": + version: 6.21.0 + resolution: "undici-types@npm:6.21.0" + checksum: 10c0/c01ed51829b10aa72fc3ce64b747f8e74ae9b60eafa19a7b46ef624403508a54c526ffab06a14a26b3120d055e1104d7abe7c9017e83ced038ea5cf52f8d5e04 + languageName: node + linkType: hard + +"unique-filename@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-filename@npm:4.0.0" + dependencies: + unique-slug: "npm:^5.0.0" + checksum: 10c0/38ae681cceb1408ea0587b6b01e29b00eee3c84baee1e41fd5c16b9ed443b80fba90c40e0ba69627e30855570a34ba8b06702d4a35035d4b5e198bf5a64c9ddc + languageName: node + linkType: hard + +"unique-slug@npm:^5.0.0": + version: 5.0.0 + resolution: "unique-slug@npm:5.0.0" + dependencies: + imurmurhash: "npm:^0.1.4" + checksum: 10c0/d324c5a44887bd7e105ce800fcf7533d43f29c48757ac410afd42975de82cc38ea2035c0483f4de82d186691bf3208ef35c644f73aa2b1b20b8e651be5afd293 + languageName: node + linkType: hard + +"url-join@npm:^5.0.0": + version: 5.0.0 + resolution: "url-join@npm:5.0.0" + checksum: 10c0/ed2b166b4b5a98adcf6828a48b6bd6df1dac4c8a464a73cf4d8e2457ed410dd8da6be0d24855b86026cd7f5c5a3657c1b7b2c7a7c5b8870af17635a41387b04c + languageName: node + linkType: hard + +"vite-node@npm:3.2.3": + version: 3.2.3 + resolution: "vite-node@npm:3.2.3" + dependencies: + cac: "npm:^6.7.14" + debug: "npm:^4.4.1" + es-module-lexer: "npm:^1.7.0" + pathe: "npm:^2.0.3" + vite: "npm:^5.0.0 || ^6.0.0 || ^7.0.0-0" + bin: + vite-node: vite-node.mjs + checksum: 10c0/b952b0d9e45662506ea7303ac87d08e02f1e3355777cf7d426f211292c4f87e8837aef589e552bb11404d1bc0a9bd18871ce6ba874b5f0bb171f8e010de20a11 + languageName: node + linkType: hard + +"vite@npm:^5.0.0 || ^6.0.0 || ^7.0.0-0": + version: 7.0.0-beta.0 + resolution: "vite@npm:7.0.0-beta.0" + dependencies: + esbuild: "npm:^0.25.0" + fdir: "npm:^6.4.4" + fsevents: "npm:~2.3.3" + picomatch: "npm:^4.0.2" + postcss: "npm:^8.5.3" + rollup: "npm:^4.40.0" + tinyglobby: "npm:^0.2.14" + peerDependencies: + "@types/node": ^20.19.0 || >=22.12.0 + jiti: ">=1.21.0" + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: ">=0.54.8" + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + bin: + vite: bin/vite.js + checksum: 10c0/d13907d67b4991a2862dafe6a31d10ffe28f26ba04e511049e9d86d06293b3a8d6733c896c8fb38e3f2d5805d240e3cad27700f3c42536602035e4c324b48d58 + languageName: node + linkType: hard + +"vitest@npm:^3.2.2": + version: 3.2.3 + resolution: "vitest@npm:3.2.3" + dependencies: + "@types/chai": "npm:^5.2.2" + "@vitest/expect": "npm:3.2.3" + "@vitest/mocker": "npm:3.2.3" + "@vitest/pretty-format": "npm:^3.2.3" + "@vitest/runner": "npm:3.2.3" + "@vitest/snapshot": "npm:3.2.3" + "@vitest/spy": "npm:3.2.3" + "@vitest/utils": "npm:3.2.3" + chai: "npm:^5.2.0" + debug: "npm:^4.4.1" + expect-type: "npm:^1.2.1" + magic-string: "npm:^0.30.17" + pathe: "npm:^2.0.3" + picomatch: "npm:^4.0.2" + std-env: "npm:^3.9.0" + tinybench: "npm:^2.9.0" + tinyexec: "npm:^0.3.2" + tinyglobby: "npm:^0.2.14" + tinypool: "npm:^1.1.0" + tinyrainbow: "npm:^2.0.0" + vite: "npm:^5.0.0 || ^6.0.0 || ^7.0.0-0" + vite-node: "npm:3.2.3" + why-is-node-running: "npm:^2.3.0" + peerDependencies: + "@edge-runtime/vm": "*" + "@types/debug": ^4.1.12 + "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 + "@vitest/browser": 3.2.3 + "@vitest/ui": 3.2.3 + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@types/debug": + optional: true + "@types/node": + optional: true + "@vitest/browser": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + bin: + vitest: vitest.mjs + checksum: 10c0/1d853016622f32020e91cc72348d0dc642bde2ddcbd648655a9d33d420375c7cbd6f1a6f5c4398a5d4f59b8c2b120e62eba49fb37f8042e5d4c688b7e60148ef + languageName: node + linkType: hard + +"webidl-conversions@npm:^3.0.0": + version: 3.0.1 + resolution: "webidl-conversions@npm:3.0.1" + checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db + languageName: node + linkType: hard + +"whatwg-url@npm:^5.0.0": + version: 5.0.0 + resolution: "whatwg-url@npm:5.0.0" + dependencies: + tr46: "npm:~0.0.3" + webidl-conversions: "npm:^3.0.0" + checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5 + languageName: node + linkType: hard + +"which@npm:^2.0.1": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: "npm:^2.0.0" + bin: + node-which: ./bin/node-which + checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f + languageName: node + linkType: hard + +"which@npm:^5.0.0": + version: 5.0.0 + resolution: "which@npm:5.0.0" + dependencies: + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: 10c0/e556e4cd8b7dbf5df52408c9a9dd5ac6518c8c5267c8953f5b0564073c66ed5bf9503b14d876d0e9c7844d4db9725fb0dcf45d6e911e17e26ab363dc3965ae7b + languageName: node + linkType: hard + +"why-is-node-running@npm:^2.3.0": + version: 2.3.0 + resolution: "why-is-node-running@npm:2.3.0" + dependencies: + siginfo: "npm:^2.0.0" + stackback: "npm:0.0.2" + bin: + why-is-node-running: cli.js + checksum: 10c0/1cde0b01b827d2cf4cb11db962f3958b9175d5d9e7ac7361d1a7b0e2dc6069a263e69118bd974c4f6d0a890ef4eedfe34cf3d5167ec14203dbc9a18620537054 + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: "npm:^4.0.0" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: "npm:^6.1.0" + string-width: "npm:^5.0.1" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 + languageName: node + linkType: hard + +"yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a + languageName: node + linkType: hard + +"yallist@npm:^5.0.0": + version: 5.0.0 + resolution: "yallist@npm:5.0.0" + checksum: 10c0/a499c81ce6d4a1d260d4ea0f6d49ab4da09681e32c3f0472dee16667ed69d01dae63a3b81745a24bd78476ec4fcf856114cb4896ace738e01da34b2c42235416 + languageName: node + linkType: hard + +"zod@npm:^3.25.56": + version: 3.25.56 + resolution: "zod@npm:3.25.56" + checksum: 10c0/3800f01d4b1df932b91354eb1e648f69cc7e5561549e6d2bf83827d930a5f33bbf92926099445f6fc1ebb64ca9c6513ef9ae5e5409cfef6325f354bcf6fc9a24 + languageName: node + linkType: hard + +"zx@npm:^8.1.9": + version: 8.5.5 + resolution: "zx@npm:8.5.5" + bin: + zx: build/cli.js + checksum: 10c0/9c69e5a75b49b796211812625564980d0a86079a11011b397c4c77d256e3fe0a76b5ec7134db4d598e156f84e07981d8692544715feb8ff77adfae60faa356fc + languageName: node + linkType: hard diff --git a/cloud/packages/ci-runner/Dockerfile b/cloud/packages/ci-runner/Dockerfile new file mode 100644 index 0000000000..bd7a621b00 --- /dev/null +++ b/cloud/packages/ci-runner/Dockerfile @@ -0,0 +1,9 @@ +FROM alpine:latest AS builder + +# FROM gcr.io/kaniko-project/executor:latest +FROM ghcr.io/rivet-gg/executor@sha256:439d4dbb0f3f8c1c6c2195e144d29195b4930b87166a6fae32061b564a6baa9e +COPY --from=builder /bin/sh /bin/sh +COPY --from=builder /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 + +# HACK: Use env vars to interpolate args bc Rivet doesn't support passing args +ENTRYPOINT ["/bin/sh", "-c", "/kaniko/executor --context=${CONTEXT_URL} --destination=${DESTINATION} --upload-tar=${OUTPUT_URL} --dockerfile=${DOCKERFILE_PATH} --no-push --single-snapshot --verbosity=info"] diff --git a/cloud/rivet.json b/cloud/rivet.json new file mode 100644 index 0000000000..08356e63c5 --- /dev/null +++ b/cloud/rivet.json @@ -0,0 +1,15 @@ +{ + "actors": { + "ci-manager": { + "dockerfile": "packages/ci-manager/Dockerfile", + "build_path": "packages/ci-manager" + }, + "ci-runner": { + "dockerfile": "packages/ci-runner/Dockerfile", + "build_path": "packages/ci-runner", + "unstable": { + "allow_root": true + } + } + } +} diff --git a/examples/system-test-actor/rivet.jsonc b/examples/system-test-actor/rivet.jsonc index e828151bb7..cc40dad97c 100644 --- a/examples/system-test-actor/rivet.jsonc +++ b/examples/system-test-actor/rivet.jsonc @@ -4,10 +4,7 @@ // "script": "src/isolate/main.ts" // }, "ws-container": { - "dockerfile": "Dockerfile", - // "unstable": { - // "compression": "none" - // } + "dockerfile": "Dockerfile" } } } diff --git a/package.json b/package.json index 120077fe1f..7d6ac16177 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "workspaces": [ "frontend/apps/*", "frontend/packages/*", + "cloud/packages/*", "site", "sdks/api/runtime/typescript", "sdks/api/full/typescript", @@ -25,17 +26,6 @@ }, "resolutions": { "react": "^19", - "react-dom": "^19", - "actor-core": "portal:../actor-core/packages/actor-core", - "@actor-core/cli": "portal:../actor-core/packages/actor-core-cli", - "create-actor": "portal:../../actor-core/packages/create-actor", - "@actor-core/memory": "portal:../actor-core/packages/drivers/memory", - "@actor-core/redis": "portal:../actor-core/packages/drivers/redis", - "@actor-core/framework-base": "portal:../actor-core/packages/frameworks/framework-base", - "@actor-core/react": "portal:../actor-core/packages/frameworks/react", - "@actor-core/bun": "portal:../actor-core/packages/platforms/bun", - "@actor-core/cloudflare-workers": "portal:../actor-core/packages/platforms/cloudflare-workers", - "@actor-core/nodejs": "portal:../actor-core/packages/platforms/nodejs", - "@actor-core/rivet": "portal:../actor-core/packages/platforms/rivet" + "react-dom": "^19" } } diff --git a/packages/toolchain/cli/src/main.rs b/packages/toolchain/cli/src/main.rs index ab9fd08c53..6520d125ee 100644 --- a/packages/toolchain/cli/src/main.rs +++ b/packages/toolchain/cli/src/main.rs @@ -64,10 +64,10 @@ async fn main_async() -> ExitCode { return err.exit_code(); } else if let Some(err) = err.downcast_ref::() { // Don't report error since this is a user error - eprintln!("\n{err}"); + eprintln!("\n{err:?}"); } else { // This is an internal error, report error - eprintln!("\n{err}"); + eprintln!("\n{err:?}"); report_error(err).await; } diff --git a/packages/toolchain/toolchain/Cargo.toml b/packages/toolchain/toolchain/Cargo.toml index 13fd96d798..89edd3f718 100644 --- a/packages/toolchain/toolchain/Cargo.toml +++ b/packages/toolchain/toolchain/Cargo.toml @@ -14,6 +14,7 @@ console = "0.15" const_format = "0.2.32" deno-embed.workspace = true dirs = "5.0" +flate2 = "1.0" futures-util = "0.3" humansize = "1.1" ignore = "0.4" diff --git a/packages/toolchain/toolchain/src/config/build/docker.rs b/packages/toolchain/toolchain/src/config/build/docker.rs index 665034a993..214bc7ffba 100644 --- a/packages/toolchain/toolchain/src/config/build/docker.rs +++ b/packages/toolchain/toolchain/src/config/build/docker.rs @@ -65,6 +65,9 @@ pub enum BuildMethod { /// Create & use a Buildx builder on this machine. Required for cross-platform compilation. Native, + + /// Use Rivet Cloud for building. + Remote, } #[derive( diff --git a/packages/toolchain/toolchain/src/tasks/build_publish/docker.rs b/packages/toolchain/toolchain/src/tasks/build_publish/docker.rs index 55d4677977..152a188495 100644 --- a/packages/toolchain/toolchain/src/tasks/build_publish/docker.rs +++ b/packages/toolchain/toolchain/src/tasks/build_publish/docker.rs @@ -125,34 +125,50 @@ pub async fn docker_build_and_push( current_dir: &Path, push_opts: &DockerBuildPushOpts, ) -> Result { - // Build image - let build_output = docker::build::build_image( - ctx, - task.clone(), - current_dir, - &Path::new(&push_opts.dockerfile), - push_opts.build_method, - push_opts.bundle, - push_opts.compression, - push_opts.build_args.as_ref().map(|x| x.as_slice()), - push_opts.build_target.as_ref().map(String::as_str), - push_opts.allow_root, - ) - .await?; - - // Upload build - docker::push::push_tar( - ctx, - task.clone(), - &docker::push::PushOpts { - env: push_opts.env.clone(), - path: build_output.path.to_owned(), - docker_tag: build_output.tag, - bundle: push_opts.bundle, - compression: push_opts.compression, - }, - ) - .await + match push_opts.build_method { + config::build::docker::BuildMethod::Native | config::build::docker::BuildMethod::Buildx => { + // Build image + let build_output = docker::build::build_image( + ctx, + task.clone(), + current_dir, + &Path::new(&push_opts.dockerfile), + push_opts.build_method, + push_opts.bundle, + push_opts.compression, + push_opts.build_args.as_ref().map(|x| x.as_slice()), + push_opts.build_target.as_ref().map(String::as_str), + push_opts.allow_root, + ) + .await?; + + // Upload build + docker::push::push_tar( + ctx, + task.clone(), + &docker::push::PushOpts { + env: push_opts.env.clone(), + path: build_output.path.to_owned(), + docker_tag: build_output.tag, + bundle: push_opts.bundle, + compression: push_opts.compression, + }, + ) + .await + } + config::build::docker::BuildMethod::Remote => { + docker::build_remote::build_remote( + ctx, + task.clone(), + push_opts.env.clone(), + current_dir, + &Path::new(&push_opts.dockerfile), + &push_opts.build_args, + &push_opts.build_target, + ) + .await + } + } } pub struct DockerPushOpts { diff --git a/packages/toolchain/toolchain/src/util/docker/build.rs b/packages/toolchain/toolchain/src/util/docker/build.rs index 0e8e2c38b2..94d025e422 100644 --- a/packages/toolchain/toolchain/src/util/docker/build.rs +++ b/packages/toolchain/toolchain/src/util/docker/build.rs @@ -1,5 +1,5 @@ use anyhow::*; -use std::{collections::HashMap, path::Path}; +use std::{collections::HashMap, path::Path, result::Result::Ok}; use crate::{ config::{self}, @@ -17,7 +17,7 @@ pub struct BuildImageOutput { /// Builds an image and archives it to a path. pub async fn build_image( - _ctx: &ToolchainCtx, + ctx: &ToolchainCtx, task: task::TaskCtx, build_path: &Path, dockerfile: &Path, @@ -48,6 +48,7 @@ pub async fn build_image( let buildx_info = match build_method { config::build::docker::BuildMethod::Native => " (with native)", config::build::docker::BuildMethod::Buildx => " (with buildx)", + config::build::docker::BuildMethod::Remote => " (with remote)", }; task.log(format!("[Building] {}{buildx_info}", dockerfile.display())); @@ -70,103 +71,30 @@ pub async fn build_image( let image_tag = super::generate_unique_image_tag(); match build_method { config::build::docker::BuildMethod::Native => { - let mut build_cmd = shell_cmd("docker"); - build_cmd - .arg("build") - .arg("--platform") - .arg("linux/amd64") - .arg("--file") - .arg(dockerfile) - .arg("--tag") - .arg(&image_tag) - .args( - &build_arg_flags - .iter() - .map(|(k, v)| format!("--build-arg={}={}", k, v)) - .collect::>(), - ); - if let Some(build_target) = build_target { - build_cmd.arg("--target").arg(build_target); - } - build_cmd.arg(build_path); - cmd::execute_docker_cmd( + build_native( task.clone(), - build_cmd, - "Docker image failed to build (native)", + build_path, + dockerfile, + &build_arg_flags, + build_target, + &image_tag, ) .await?; } config::build::docker::BuildMethod::Buildx => { - let builder_name = "rivet_toolchain"; - - // Determine if needs to create a new builder - let mut inspect_cmd = shell_cmd("docker"); - inspect_cmd.arg("buildx").arg("inspect").arg(builder_name); - let inspect_output = cmd::execute_docker_cmd_silent_fallible(inspect_cmd).await?; - - if !inspect_output.status.success() - && String::from_utf8(inspect_output.stderr.clone())? - .contains(&format!("no builder \"{builder_name}\" found")) - { - // Create new builder - - let mut build_cmd = shell_cmd("docker"); - build_cmd - .arg("buildx") - .arg("create") - .arg("--name") - .arg(builder_name) - .arg("--driver") - .arg("docker-container") - .arg("--platform") - .arg("linux/amd64"); - cmd::execute_docker_cmd( - task.clone(), - build_cmd, - "Failed to create Docker Buildx builder", - ) - .await?; - } else { - // Builder exists - - cmd::error_for_output_failure( - &inspect_output, - "Failed to inspect Docker Buildx runner", - )?; - } - - // Build image - let mut build_cmd = shell_cmd("docker"); - build_cmd - .arg("buildx") - .arg("build") - .arg("--builder") - .arg(builder_name) - .arg("--platform") - .arg("linux/amd64") - .arg("--file") - .arg(dockerfile) - .arg("--tag") - .arg(&image_tag) - .args( - &build_arg_flags - .iter() - .map(|(k, v)| format!("--build-arg={}={}", k, v)) - .collect::>(), - ) - .arg("--output") - .arg("type=docker"); - if let Some(build_target) = build_target { - build_cmd.arg("--target").arg(build_target); - } - build_cmd.arg(build_path); - cmd::execute_docker_cmd( + build_buildx( task.clone(), - build_cmd, - "Docker image failed to build (buildx)", + build_path, + dockerfile, + &build_arg_flags, + build_target, + &image_tag, ) .await?; } + config::build::docker::BuildMethod::Remote => { + unreachable!() + } } // Build archive @@ -193,3 +121,106 @@ pub async fn build_image( path: build_tar_path, }) } + +async fn build_native( + task: task::TaskCtx, + build_path: &Path, + dockerfile: &Path, + build_arg_flags: &HashMap, + build_target: Option<&str>, + image_tag: &str, +) -> Result<()> { + let mut build_cmd = shell_cmd("docker"); + build_cmd + .arg("build") + .arg("--platform") + .arg("linux/amd64") + .arg("--file") + .arg(dockerfile) + .arg("--tag") + .arg(image_tag) + .args( + &build_arg_flags + .iter() + .map(|(k, v)| format!("--build-arg={}={}", k, v)) + .collect::>(), + ); + if let Some(build_target) = build_target { + build_cmd.arg("--target").arg(build_target); + } + build_cmd.arg(build_path); + cmd::execute_docker_cmd(task, build_cmd, "Docker image failed to build (native)").await?; + Ok(()) +} + +async fn build_buildx( + task: task::TaskCtx, + build_path: &Path, + dockerfile: &Path, + build_arg_flags: &HashMap, + build_target: Option<&str>, + image_tag: &str, +) -> Result<()> { + let builder_name = "rivet_toolchain"; + + // Determine if needs to create a new builder + let mut inspect_cmd = shell_cmd("docker"); + inspect_cmd.arg("buildx").arg("inspect").arg(builder_name); + let inspect_output = cmd::execute_docker_cmd_silent_fallible(inspect_cmd).await?; + + if !inspect_output.status.success() + && String::from_utf8(inspect_output.stderr.clone())? + .contains(&format!("no builder \"{builder_name}\" found")) + { + // Create new builder + + let mut build_cmd = shell_cmd("docker"); + build_cmd + .arg("buildx") + .arg("create") + .arg("--name") + .arg(builder_name) + .arg("--driver") + .arg("docker-container") + .arg("--platform") + .arg("linux/amd64"); + cmd::execute_docker_cmd( + task.clone(), + build_cmd, + "Failed to create Docker Buildx builder", + ) + .await?; + } else { + // Builder exists + + cmd::error_for_output_failure(&inspect_output, "Failed to inspect Docker Buildx runner")?; + } + + // Build image + let mut build_cmd = shell_cmd("docker"); + build_cmd + .arg("buildx") + .arg("build") + .arg("--builder") + .arg(builder_name) + .arg("--platform") + .arg("linux/amd64") + .arg("--file") + .arg(dockerfile) + .arg("--tag") + .arg(image_tag) + .args( + &build_arg_flags + .iter() + .map(|(k, v)| format!("--build-arg={}={}", k, v)) + .collect::>(), + ) + .arg("--output") + .arg("type=docker"); + if let Some(build_target) = build_target { + build_cmd.arg("--target").arg(build_target); + } + build_cmd.arg(build_path); + cmd::execute_docker_cmd(task, build_cmd, "Docker image failed to build (buildx)").await?; + Ok(()) +} diff --git a/packages/toolchain/toolchain/src/util/docker/build_remote.rs b/packages/toolchain/toolchain/src/util/docker/build_remote.rs new file mode 100644 index 0000000000..5171710300 --- /dev/null +++ b/packages/toolchain/toolchain/src/util/docker/build_remote.rs @@ -0,0 +1,611 @@ +use anyhow::*; +use flate2::{write::GzEncoder, Compression}; +use serde_json::json; +use std::{collections::HashMap, io::Write, path::Path, result::Result::Ok, time::Duration}; +use tempfile::NamedTempFile; +use uuid::Uuid; + +use crate::{ + config::{self}, + project::environment::TEMPEnvironment, + tasks::env, + toolchain_ctx::ToolchainCtx, + util::{docker::push, task}, +}; + +use rivet_api::{apis, models}; + +const DEFAULT_CI_REGION: &str = "atl"; + +/// Environment slug for the CI environment. +const CI_ENVIRONMENT_ID: &str = "ci"; + +/// Release URLs for CI components +/// +/// Uploaded with ./scripts/cloud/upload-builds.ts +const CI_MANAGER_RELEASE_URL: &str = + "https://releases.rivet.gg/ci-manager/2025-06-10-09-25-53-481Z/image.tar"; +const CI_RUNNER_RELEASE_URL: &str = + "https://releases.rivet.gg/ci-runner/2025-06-10-08-48-55-332Z/image.tar"; + +pub async fn build_remote( + ctx: &ToolchainCtx, + task: task::TaskCtx, + environment: TEMPEnvironment, + build_path: &Path, + dockerfile: &Path, + _build_arg_flags: &Option>, + _build_target: &Option, +) -> Result { + task.log("[Remote Build] Starting remote build process"); + + // Get or create CI namespace + let _ci_namespace = get_or_create_ci_namespace(ctx, task.clone()).await?; + + // Get build IDs for CI manager and runner + let ci_manager_build_id = upload_ci_manager_build(ctx, task.clone()).await?; + let ci_runner_build_id = upload_ci_runner_build(ctx, task.clone()).await?; + + // Get or create ci-runner actor + let (ci_runner_actor_id, ci_runner_endpoint) = + get_or_create_ci_manager_actor(ctx, task.clone(), ci_manager_build_id, ci_runner_build_id) + .await?; + + // Upload build context + let build_id = upload_build_context( + ctx, + task.clone(), + &environment, + build_path, + dockerfile, + &ci_runner_actor_id, + &ci_runner_endpoint, + ) + .await?; + + // Poll build status + let build_id = poll_build_status(ctx, task.clone(), &build_id, &ci_runner_endpoint).await?; + + Ok(push::PushOutput { build_id }) +} + +async fn get_or_create_ci_namespace( + ctx: &ToolchainCtx, + task: task::TaskCtx, +) -> Result { + // Look for existing CI namespace + let existing_namespace = ctx + .project + .namespaces + .iter() + .find(|ns| ns.name_id == CI_ENVIRONMENT_ID); + + if let Some(namespace) = existing_namespace { + task.log(format!( + "[Remote Build] Found existing CI namespace: {}", + namespace.name_id + )); + return Ok(TEMPEnvironment::from(namespace.clone())); + } + + // Create new CI namespace using the default version + task.log("[Remote Build] Creating new CI namespace"); + + // Get the default version (first version if available) + let default_version_id = ctx + .project + .versions + .first() + .map(|v| v.version_id) + .context("No versions available for project")?; + + let create_response = + apis::cloud_games_namespaces_api::cloud_games_namespaces_create_game_namespace( + &ctx.openapi_config_cloud, + &ctx.project.game_id.to_string(), + models::CloudGamesNamespacesCreateGameNamespaceRequest { + name_id: CI_ENVIRONMENT_ID.to_string(), + display_name: "Continuous Integration".to_string(), + version_id: default_version_id, + }, + ) + .await + .context("Failed to create CI namespace")?; + + // Fetch the full namespace details + let namespace_response = + apis::cloud_games_namespaces_api::cloud_games_namespaces_get_game_namespace_by_id( + &ctx.openapi_config_cloud, + &ctx.project.game_id.to_string(), + &create_response.namespace_id.to_string(), + ) + .await + .context("Failed to get created CI namespace details")?; + + Ok(TEMPEnvironment::from(*namespace_response.namespace)) +} + +async fn upload_ci_manager_build(ctx: &ToolchainCtx, task: task::TaskCtx) -> Result { + upload_ci_build(ctx, task, "ci-manager", CI_MANAGER_RELEASE_URL).await +} + +async fn upload_ci_runner_build(ctx: &ToolchainCtx, task: task::TaskCtx) -> Result { + upload_ci_build(ctx, task, "ci-runner", CI_RUNNER_RELEASE_URL).await +} + +async fn upload_ci_build( + ctx: &ToolchainCtx, + task: task::TaskCtx, + name: &str, + url: &str, +) -> Result { + task.log(format!( + "[Remote Build] Checking for existing {} build", + name + )); + + // Get the CI environment + let ci_env = get_ci_environment(ctx, task.clone()) + .await + .context("Failed to get CI environment")?; + + // Check if build already exists with this URL tag + let tags_filter = serde_json::to_string(&serde_json::json!({ + "name": name, + "url": url + }))?; + + let builds_response = apis::builds_api::builds_list( + &ctx.openapi_config_cloud, + Some(&ctx.project.name_id), + Some(&ci_env.slug), + Some(&tags_filter), + ) + .await + .context("Failed to list builds")?; + + // If build exists, return its ID + if let Some(existing_build) = builds_response.builds.first() { + task.log(format!( + "[Remote Build] Found existing {} build: {}", + name, existing_build.id + )); + return Ok(existing_build.id); + } + + // Download the image.tar + task.log(format!("[Remote Build] Downloading {} from {}", name, url)); + let temp_file = download_file(url) + .await + .context("Failed to download image.tar")?; + + // Upload the build using push_tar + task.log(format!("[Remote Build] Uploading {} build", name)); + let push_opts = push::PushOpts { + env: ci_env.clone(), + path: temp_file.path().to_path_buf(), + docker_tag: format!("{}:{}", name, Uuid::new_v4()), + bundle: config::build::docker::BundleKind::DockerImage, + compression: config::build::Compression::None, + }; + + let push_output = push::push_tar(ctx, task.clone(), &push_opts) + .await + .context("Failed to upload build")?; + + // Patch tags on the build + task.log(format!("[Remote Build] Tagging {} build", name)); + let patch_tags = serde_json::json!({ + "name": name, + "url": url + }); + + apis::builds_api::builds_patch_tags( + &ctx.openapi_config_cloud, + &push_output.build_id.to_string(), + models::BuildsPatchBuildTagsRequest { + tags: Some(patch_tags), + exclusive_tags: None, + }, + Some(&ctx.project.name_id), + Some(&ci_env.slug), + ) + .await + .context("Failed to patch build tags")?; + + task.log(format!( + "[Remote Build] {} build uploaded successfully: {}", + name, push_output.build_id + )); + Ok(push_output.build_id) +} + +async fn get_ci_environment(ctx: &ToolchainCtx, task: task::TaskCtx) -> Result { + get_or_create_ci_namespace(ctx, task).await +} + +async fn download_file(url: &str) -> Result { + let response = reqwest::get(url) + .await + .context("Failed to fetch file")? + .error_for_status() + .context("HTTP error while fetching file")?; + + let mut temp_file = NamedTempFile::new().context("Failed to create temporary file")?; + + let bytes = response + .bytes() + .await + .context("Failed to read response body")?; + + temp_file + .write_all(&bytes) + .context("Failed to write to temporary file")?; + + temp_file + .flush() + .context("Failed to flush temporary file")?; + + Ok(temp_file) +} + +async fn get_or_create_ci_manager_actor( + ctx: &ToolchainCtx, + task: task::TaskCtx, + ci_manager_build_id: Uuid, + ci_runner_build_id: Uuid, +) -> Result<(String, String)> { + // Check if default region exists + let regions_response = apis::regions_api::regions_list( + &ctx.openapi_config_cloud, + Some(&ctx.project.name_id), + Some(CI_ENVIRONMENT_ID), + ) + .await + .context("Failed to list regions")?; + + let default_region_exists = regions_response + .regions + .iter() + .any(|region| region.id == DEFAULT_CI_REGION); + + if default_region_exists { + task.log(format!("[Remote Build] {DEFAULT_CI_REGION} region found")); + } else { + task.log(format!( + "[Remote Build] {DEFAULT_CI_REGION} region not found, will not specify region" + )); + } + + // Look for existing ci-manager actor + let tags_json = serde_json::to_string(&serde_json::json!({"name": "ci-manager"}))?; + let actors_response = apis::actors_api::actors_list( + &ctx.openapi_config_cloud, + Some(&ctx.project.name_id), + Some(CI_ENVIRONMENT_ID), + None, + Some(&tags_json), + Some(false), + None, + ) + .await + .context("Failed to list actors")?; + + if let Some(existing_actor) = actors_response.actors.iter().find(|actor| { + actor + .tags + .as_ref() + .and_then(|tags| tags.get("name")) + .and_then(|v| v.as_str()) + == Some("ci-manager") + }) { + task.log(format!( + "[Remote Build] Found existing ci-manager actor: {}", + existing_actor.id + )); + + let endpoint = existing_actor + .network + .ports + .get("http") + .and_then(|port| port.hostname.as_ref()) + .context("CI manager actor endpoint not available")?; + + return Ok((existing_actor.id.to_string(), endpoint.clone())); + } + + // Create new ci-manager actor + task.log("[Remote Build] Creating new ci-manager actor"); + let create_response = apis::actors_api::actors_create( + &ctx.openapi_config_cloud, + models::ActorsCreateActorRequest { + region: if default_region_exists { + Some(DEFAULT_CI_REGION.to_string()) + } else { + None + }, + tags: Some(json!({"name": "ci-manager"})), + build: Some(ci_manager_build_id.into()), + build_tags: None, + runtime: Some(Box::new(models::ActorsCreateActorRuntimeRequest { + environment: Some(HashMap::from([ + ("KANIKO_EXECUTION_MODE".into(), "rivet".into()), + ("KANIKO_BUILD_ID".into(), ci_runner_build_id.to_string()), + ("RIVET_CLOUD_TOKEN".into(), ctx.access_token.clone()), + ("RIVET_PROJECT".into(), ctx.project.name_id.clone()), + ("RIVET_ENVIRONMENT".into(), CI_ENVIRONMENT_ID.into()), + ])), + network: None, + })), + network: Some(Box::new(models::ActorsCreateActorNetworkRequest { + mode: Some(models::ActorsNetworkMode::Bridge), + ports: Some(std::collections::HashMap::from([( + "http".to_string(), + models::ActorsCreateActorPortRequest { + protocol: models::ActorsPortProtocol::Https, + routing: Some(Box::new(models::ActorsPortRouting { + guard: Some(serde_json::json!({})), + host: None, + })), + internal_port: Some(3000), + }, + )])), + wait_ready: Some(true), + })), + resources: Some(Box::new(models::ActorsResources { + cpu: 1000, + memory: 1024, + })), + lifecycle: Some(Box::new(models::ActorsLifecycle { + kill_timeout: Some(30000), + durable: Some(true), + })), + }, + Some(&ctx.project.name_id), + Some(CI_ENVIRONMENT_ID), + None, + ) + .await + .context("Failed to create ci-manager actor")?; + + let endpoint = create_response + .actor + .network + .ports + .get("http") + .and_then(|port| port.hostname.as_ref()) + .context("CI manager actor endpoint not available")?; + + Ok((create_response.actor.id.to_string(), endpoint.clone())) +} + +async fn create_build_context_archive( + task: task::TaskCtx, + build_path: &Path, + _dockerfile: &Path, +) -> Result> { + task.log(format!( + "[Remote Build] Creating gzipped tar archive from build path: {:?}", + build_path + )); + + // Create a gzipped tar archive of the build context + let mut archive_data = Vec::new(); + { + let gz_encoder = GzEncoder::new(&mut archive_data, Compression::default()); + let mut tar = tar::Builder::new(gz_encoder); + + // Add the entire build directory to the archive + tar.append_dir_all(".", build_path) + .context("Failed to create build context archive")?; + + tar.finish().context("Failed to finalize tar archive")?; + } + + task.log(format!( + "[Remote Build] Created gzipped archive ({} bytes)", + archive_data.len() + )); + Ok(archive_data) +} + +async fn upload_build_context( + _ctx: &ToolchainCtx, + task: task::TaskCtx, + environment: &TEMPEnvironment, + build_path: &Path, + dockerfile: &Path, + _ci_manager_actor_id: &str, + ci_manager_endpoint: &str, +) -> Result { + let server_url = format!("https://{}", ci_manager_endpoint); + task.log(format!( + "[Remote Build] Using CI manager endpoint: {}", + server_url + )); + + // Create build context tar.gz + let context_buffer = create_build_context_archive(task.clone(), build_path, dockerfile).await?; + let build_name = "rivet-remote-build"; + + // Prepare multipart form data + task.log("[Remote Build] Uploading build context..."); + + // Create FormData-like structure using reqwest + let form = reqwest::multipart::Form::new() + .text("buildName", build_name) + .text("environmentId", environment.slug.to_string()) + .text( + "dockerfilePath", + dockerfile + .file_name() + .and_then(|name| name.to_str()) + .unwrap_or("Dockerfile") + .to_string(), + ) + .part( + "context", + reqwest::multipart::Part::bytes(context_buffer) + .file_name("context.tar.gz") + .mime_str("application/gzip")?, + ); + + // Submit build + let encoded_server_url = server_url.replace(":", "%3A").replace("/", "%2F"); + let response = reqwest::Client::new() + .post(&format!( + "{}/builds?serverUrl={}", + server_url, encoded_server_url + )) + .multipart(form) + .send() + .await + .context("Failed to upload build context")?; + + if !response.status().is_success() { + let status = response.status(); + let error_text = response + .text() + .await + .unwrap_or_else(|_| "Unknown error".to_string()); + bail!("Build upload failed with status {}: {}", status, error_text); + } + + let result: serde_json::Value = response + .json() + .await + .context("Failed to parse build upload response")?; + + let build_id = result + .get("buildId") + .and_then(|v| v.as_str()) + .context("Build response missing buildId")? + .to_string(); + + task.log(format!( + "[Remote Build] Build context uploaded successfully, build ID: {}", + build_id + )); + Ok(build_id) +} + +async fn poll_build_status( + _ctx: &ToolchainCtx, + task: task::TaskCtx, + build_id: &str, + ci_manager_endpoint: &str, +) -> Result { + let server_url = format!("https://{}", ci_manager_endpoint); + + // Poll build status until completion + task.log("[Remote Build] Polling build status..."); + let max_attempts = 900; // 30 minutes + let interval = Duration::from_secs(2); + + for attempt in 0..max_attempts { + tokio::time::sleep(interval).await; + + let response = reqwest::Client::new() + .get(&format!("{}/builds/{}", server_url, build_id)) + .send() + .await; + + match response { + Ok(res) => { + if res.status().is_success() { + let build_info: serde_json::Value = res + .json() + .await + .context("Failed to parse build status response")?; + + let status = build_info + .get("status") + .and_then(|s| s.get("type")) + .and_then(|t| t.as_str()) + .unwrap_or("unknown"); + + task.log(format!("[Remote Build] Build status: {}", status)); + + match status { + "success" => { + task.log("[Remote Build] Build completed successfully"); + let build_id_raw = build_info + .get("status") + .and_then(|x| x.get("data")) + .and_then(|x| x.get("buildId")) + .and_then(|x| x.as_str()) + .context("missing build id in status")?; + let build_id = Uuid::parse_str(&build_id_raw)?; + return Ok(build_id); + } + "failure" => { + let reason = build_info + .get("status") + .and_then(|s| s.get("data")) + .and_then(|d| d.get("reason")) + .and_then(|r| r.as_str()) + .unwrap_or("Unknown error"); + bail!("Remote build failed: {}", reason); + } + _ => { + // Continue polling for other statuses (pending, running, etc.) + } + } + } else { + task.log(format!( + "[Remote Build] Poll attempt {} failed: HTTP {}", + attempt + 1, + res.status() + )); + } + } + Err(e) => { + task.log(format!( + "[Remote Build] Poll attempt {} failed: {}", + attempt + 1, + e + )); + } + } + + if attempt == max_attempts - 1 { + bail!("Build polling timeout after {} attempts", max_attempts); + } + } + + bail!("timed out polling status") +} + +async fn get_build_by_tags( + ctx: &ToolchainCtx, + task: task::TaskCtx, + environment: &TEMPEnvironment, +) -> Result { + // List builds in the project to find one matching our build + task.log("[Remote Build] Listing builds to find final build..."); + + // Create tags filter for the remote build + let tags_filter = serde_json::to_string(&serde_json::json!({ + "name": "rivet-remote-build" + }))?; + + let builds_response = apis::builds_api::builds_list( + &ctx.openapi_config_cloud, + Some(&ctx.project.name_id), + Some(&environment.slug), + Some(&tags_filter), + ) + .await + .context("Failed to list builds")?; + + // Get the first matching build + if let Some(matching_build) = builds_response.builds.iter().next() { + task.log(format!( + "[Remote Build] Found matching build: {}", + matching_build.id + )); + Ok(matching_build.id) + } else { + bail!("No matching build found"); + } +} diff --git a/packages/toolchain/toolchain/src/util/docker/mod.rs b/packages/toolchain/toolchain/src/util/docker/mod.rs index 666f2fb929..c02609481f 100644 --- a/packages/toolchain/toolchain/src/util/docker/mod.rs +++ b/packages/toolchain/toolchain/src/util/docker/mod.rs @@ -1,6 +1,7 @@ pub mod archive; pub mod build; pub mod push; +pub mod build_remote; pub mod users; use uuid::Uuid; diff --git a/scripts/cloud/upload-builds.ts b/scripts/cloud/upload-builds.ts new file mode 100755 index 0000000000..70f0eb478c --- /dev/null +++ b/scripts/cloud/upload-builds.ts @@ -0,0 +1,83 @@ +#!/usr/bin/env tsx + +/** + * Build and upload CI manager and runner Docker images + */ + +import { $, cd } from "zx"; +import { mkdtempSync, mkdirSync, rmSync } from "fs"; +import { tmpdir } from "os"; +import { join } from "path"; +import { dirname } from "path"; +import { fileURLToPath } from "url"; + +// Get the directory where this script is located +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const projectRoot = join(__dirname, '../../'); + +// Generate ISO date with milliseconds for upload path +const isoDate = new Date().toISOString().replace(/[:\.T]/g, "-"); + +const COMPONENTS = ['ci-manager', 'ci-runner']; + +async function main() { + // Get credentials + const awsAccessKeyId = process.env.R2_RELEASES_ACCESS_KEY_ID || + (await $({ quiet: true })`op read "op://Engineering/rivet-releases R2 Upload/username"`).stdout.trim(); + const awsSecretAccessKey = process.env.R2_RELEASES_SECRET_ACCESS_KEY || + (await $({ quiet: true })`op read "op://Engineering/rivet-releases R2 Upload/password"`).stdout.trim(); + + // Create temp directory + const tempDir = mkdtempSync(join(tmpdir(), 'ci-builds-')); + console.log(`Using temp directory: ${tempDir}`); + + const uploadedUrls: string[] = []; + + try { + for (const component of COMPONENTS) { + console.log(`\nBuilding ${component}...`); + + const componentPath = join(projectRoot, 'cloud/packages', component); + const tarPath = join(tempDir, `${component}.tar`); + + // Build Docker image + console.log(`Building Docker image for ${component}`); + await $`docker build -t ${component}:latest ${componentPath}`; + + // Save Docker image to tar file + console.log(`Saving ${component} image to tar file`); + await $`docker save -o ${tarPath} ${component}:latest`; + + // Upload to S3 + const uploadPath = `${component}/${isoDate}/image.tar`; + console.log(`Uploading ${component} to s3://rivet-releases/${uploadPath}`); + + await $({ + env: { + ...process.env, + AWS_ACCESS_KEY_ID: awsAccessKeyId, + AWS_SECRET_ACCESS_KEY: awsSecretAccessKey, + AWS_DEFAULT_REGION: "auto", + } + })`aws s3 cp ${tarPath} s3://rivet-releases/${uploadPath} --content-type application/octet-stream --endpoint-url https://2a94c6a0ced8d35ea63cddc86c2681e7.r2.cloudflarestorage.com`; + + const url = `https://releases.rivet.gg/${uploadPath}`; + uploadedUrls.push(url); + console.log(`${component} upload complete!`); + } + } finally { + // Clean up temp directory + console.log(`Cleaning up temp directory: ${tempDir}`); + rmSync(tempDir, { recursive: true, force: true }); + } + + console.log("\nAll builds and uploads complete!"); + console.log("\nUploaded images:"); + uploadedUrls.forEach(url => console.log(` ${url}`)); +} + +main().catch(error => { + console.error(`Error: ${error}`); + process.exit(1); +}); diff --git a/yarn.lock b/yarn.lock index 79aa99981e..90f7aeb286 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,57 +5,52 @@ __metadata: version: 8 cacheKey: 10c0 -"@actor-core/cli@portal:../actor-core/packages/actor-core-cli::locator=rivet%40workspace%3A.": - version: 0.0.0-use.local - resolution: "@actor-core/cli@portal:../actor-core/packages/actor-core-cli::locator=rivet%40workspace%3A." +"@actor-core/cli@npm:0.9.0-rc.1": + version: 0.9.0-rc.1 + resolution: "@actor-core/cli@npm:0.9.0-rc.1" dependencies: - "@actor-core/nodejs": "workspace:^" + "@actor-core/nodejs": "npm:^0.9.0-rc.1" "@sentry/profiling-node": "npm:^9.3.0" bundle-require: "npm:^5.1.0" chokidar: "npm:^4.0.3" esbuild: "npm:^0.25.1" + invariant: "npm:^2.2.4" open: "npm:^10.1.0" yoga-wasm-web: "npm:0.3.3" bin: ac: ./dist/cli.js actor-core: ./dist/cli.js + checksum: 10c0/0fedec2cc3e8d194bd1ee021f0c53858392169153357f7f1074d3b9c88a247f2b8b36ebb73bced624927c6d881697d65947c7fbfb81a2eeea623cd870c9ee73a languageName: node - linkType: soft - -"@actor-core/memory@portal:../actor-core/packages/drivers/memory::locator=rivet%40workspace%3A.": - version: 0.0.0-use.local - resolution: "@actor-core/memory@portal:../actor-core/packages/drivers/memory::locator=rivet%40workspace%3A." - dependencies: - "@types/node": "npm:^22.13.1" - hono: "npm:^4.7.0" - peerDependencies: - actor-core: "*" - languageName: node - linkType: soft + linkType: hard -"@actor-core/nodejs@portal:../actor-core/packages/platforms/nodejs::locator=rivet%40workspace%3A.": - version: 0.0.0-use.local - resolution: "@actor-core/nodejs@portal:../actor-core/packages/platforms/nodejs::locator=rivet%40workspace%3A." +"@actor-core/nodejs@npm:0.9.0-rc.1, @actor-core/nodejs@npm:^0.9.0-rc.1": + version: 0.9.0-rc.1 + resolution: "@actor-core/nodejs@npm:0.9.0-rc.1" dependencies: - "@actor-core/memory": "workspace:*" "@hono/node-server": "npm:^1.13.8" "@hono/node-ws": "npm:^1.0.8" zod: "npm:^3.24.2" peerDependencies: + "@actor-core/file-system": "*" + "@actor-core/memory": "*" actor-core: "*" + checksum: 10c0/e7e3b722ebb2062eeec5050a0e8c7ecc4207267eec946f2d4eccc79c803540809d092a3ebccab91ebf8929612f70f5b2f4a6c16c5745434e78c015315e655f7f languageName: node - linkType: soft + linkType: hard -"@actor-core/rivet@portal:../actor-core/packages/platforms/rivet::locator=rivet%40workspace%3A.": - version: 0.0.0-use.local - resolution: "@actor-core/rivet@portal:../actor-core/packages/platforms/rivet::locator=rivet%40workspace%3A." +"@actor-core/rivet@npm:0.9.0-rc.1": + version: 0.9.0-rc.1 + resolution: "@actor-core/rivet@npm:0.9.0-rc.1" dependencies: hono: "npm:^4.7.0" + invariant: "npm:^2.2.4" zod: "npm:^3.24.2" peerDependencies: actor-core: "*" + checksum: 10c0/05271ec2c68c9648a5edb218087322ef372f14ccdfaadf9922ef680865bb4afb27120055ff8d9b36381866c1d82e5d8fae94d3c4e3aea62b5c406327c15f0bb2 languageName: node - linkType: soft + linkType: hard "@ai-sdk/anthropic@npm:^1.2.12": version: 1.2.12 @@ -151,6 +146,17 @@ __metadata: languageName: node linkType: hard +"@asteasolutions/zod-to-openapi@npm:^7.3.0": + version: 7.3.3 + resolution: "@asteasolutions/zod-to-openapi@npm:7.3.3" + dependencies: + openapi3-ts: "npm:^4.1.2" + peerDependencies: + zod: ^3.20.2 + checksum: 10c0/8c097609fa40088d76c32ab65582b73f24578cfc383090ee78a718a9e1ef442f7b6aecaa853cdff92ad6b70d8b9961613a10e8bbd14cba79e381b590cf53a68d + languageName: node + linkType: hard + "@aws-crypto/crc32@npm:5.2.0": version: 5.2.0 resolution: "@aws-crypto/crc32@npm:5.2.0" @@ -2120,6 +2126,15 @@ __metadata: languageName: node linkType: hard +"@hono/node-server@npm:^1.14.4, @hono/node-server@npm:^1.7.0": + version: 1.14.4 + resolution: "@hono/node-server@npm:1.14.4" + peerDependencies: + hono: ^4 + checksum: 10c0/1dc6296ddda0b9708cbafb406e22fb3d937505b80ec991483a5066ffa162da2cb2331b4591e7b4bbc07c62e2bea7b3a751cb0fcff33f9fba870ff95a694261ef + languageName: node + linkType: hard + "@hono/node-ws@npm:^1.0.8, @hono/node-ws@npm:^1.1.0": version: 1.1.4 resolution: "@hono/node-ws@npm:1.1.4" @@ -2132,6 +2147,29 @@ __metadata: languageName: node linkType: hard +"@hono/zod-openapi@npm:^0.19.6": + version: 0.19.8 + resolution: "@hono/zod-openapi@npm:0.19.8" + dependencies: + "@asteasolutions/zod-to-openapi": "npm:^7.3.0" + "@hono/zod-validator": "npm:^0.7.0" + peerDependencies: + hono: ">=4.3.6" + zod: 3.* + checksum: 10c0/f2af759a18d784908ff220685f1eafb4aaaf8933dbd1aa268dc0a42aa3f104a32865d46d0e01f8511cd47d224c509de2d03254539b1f9de5a5886610cf0f86ca + languageName: node + linkType: hard + +"@hono/zod-validator@npm:^0.7.0": + version: 0.7.0 + resolution: "@hono/zod-validator@npm:0.7.0" + peerDependencies: + hono: ">=3.9.0" + zod: ^3.25.0 + checksum: 10c0/8e362358348ef84a889ada450bba0a0c5b6109dacf74189153622f947e1fb66e161ef8772f169efe49d737e837d490c33efbbe094e5bb3e7a55dccd62848acd6 + languageName: node + linkType: hard + "@hookform/resolvers@npm:^3.3.4, @hookform/resolvers@npm:^3.9.0": version: 3.10.0 resolution: "@hookform/resolvers@npm:3.10.0" @@ -2719,6 +2757,15 @@ __metadata: languageName: node linkType: hard +"@jest/schemas@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/schemas@npm:29.6.3" + dependencies: + "@sinclair/typebox": "npm:^0.27.8" + checksum: 10c0/b329e89cd5f20b9278ae1233df74016ebf7b385e0d14b9f4c1ad18d096c4c19d1e687aa113a9c976b16ec07f021ae53dea811fb8c1248a50ac34fbe009fdf6be + languageName: node + linkType: hard + "@jogit/tmp-react-server-dom-nodeless@npm:^19.0.1": version: 19.0.1 resolution: "@jogit/tmp-react-server-dom-nodeless@npm:19.0.1" @@ -4865,7 +4912,7 @@ __metadata: languageName: node linkType: hard -"@rivet-gg/api@workspace:sdks/api/runtime/typescript": +"@rivet-gg/api@npm:^25.4.2, @rivet-gg/api@workspace:sdks/api/runtime/typescript": version: 0.0.0-use.local resolution: "@rivet-gg/api@workspace:sdks/api/runtime/typescript" dependencies: @@ -5159,6 +5206,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm-eabi@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.42.0" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@rollup/rollup-android-arm64@npm:4.41.1": version: 4.41.1 resolution: "@rollup/rollup-android-arm64@npm:4.41.1" @@ -5166,6 +5220,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm64@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-android-arm64@npm:4.42.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-arm64@npm:4.34.9": version: 4.34.9 resolution: "@rollup/rollup-darwin-arm64@npm:4.34.9" @@ -5180,6 +5241,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-arm64@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-darwin-arm64@npm:4.42.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-x64@npm:4.34.9": version: 4.34.9 resolution: "@rollup/rollup-darwin-x64@npm:4.34.9" @@ -5194,6 +5262,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-x64@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-darwin-x64@npm:4.42.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-freebsd-arm64@npm:4.41.1": version: 4.41.1 resolution: "@rollup/rollup-freebsd-arm64@npm:4.41.1" @@ -5201,6 +5276,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-freebsd-arm64@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.42.0" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-freebsd-x64@npm:4.41.1": version: 4.41.1 resolution: "@rollup/rollup-freebsd-x64@npm:4.41.1" @@ -5208,6 +5290,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-freebsd-x64@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-freebsd-x64@npm:4.42.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-gnueabihf@npm:4.41.1": version: 4.41.1 resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.41.1" @@ -5215,6 +5304,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-gnueabihf@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.42.0" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-musleabihf@npm:4.41.1": version: 4.41.1 resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.41.1" @@ -5222,6 +5318,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-musleabihf@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.42.0" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-gnu@npm:4.34.9": version: 4.34.9 resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.34.9" @@ -5236,6 +5339,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-gnu@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.42.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-musl@npm:4.34.9": version: 4.34.9 resolution: "@rollup/rollup-linux-arm64-musl@npm:4.34.9" @@ -5250,6 +5360,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-musl@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.42.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-loongarch64-gnu@npm:4.41.1": version: 4.41.1 resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.41.1" @@ -5257,6 +5374,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-loongarch64-gnu@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.42.0" + conditions: os=linux & cpu=loong64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-powerpc64le-gnu@npm:4.41.1": version: 4.41.1 resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.41.1" @@ -5264,6 +5388,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.42.0" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-riscv64-gnu@npm:4.41.1": version: 4.41.1 resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.41.1" @@ -5271,6 +5402,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-riscv64-gnu@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.42.0" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-riscv64-musl@npm:4.41.1": version: 4.41.1 resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.41.1" @@ -5278,6 +5416,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-riscv64-musl@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.42.0" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-s390x-gnu@npm:4.41.1": version: 4.41.1 resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.41.1" @@ -5285,6 +5430,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-s390x-gnu@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.42.0" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-gnu@npm:4.34.9": version: 4.34.9 resolution: "@rollup/rollup-linux-x64-gnu@npm:4.34.9" @@ -5299,6 +5451,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-gnu@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.42.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-musl@npm:4.34.9": version: 4.34.9 resolution: "@rollup/rollup-linux-x64-musl@npm:4.34.9" @@ -5313,6 +5472,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-musl@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.42.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-win32-arm64-msvc@npm:4.34.9": version: 4.34.9 resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.34.9" @@ -5327,6 +5493,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-arm64-msvc@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.42.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-win32-ia32-msvc@npm:4.41.1": version: 4.41.1 resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.41.1" @@ -5334,6 +5507,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-ia32-msvc@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.42.0" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@rollup/rollup-win32-x64-msvc@npm:4.34.9": version: 4.34.9 resolution: "@rollup/rollup-win32-x64-msvc@npm:4.34.9" @@ -5348,6 +5528,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-x64-msvc@npm:4.42.0": + version: 4.42.0 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.42.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@rtsao/scc@npm:^1.1.0": version: 1.1.0 resolution: "@rtsao/scc@npm:1.1.0" @@ -5812,6 +5999,13 @@ __metadata: languageName: node linkType: hard +"@sinclair/typebox@npm:^0.27.8": + version: 0.27.8 + resolution: "@sinclair/typebox@npm:0.27.8" + checksum: 10c0/ef6351ae073c45c2ac89494dbb3e1f87cc60a93ce4cde797b782812b6f97da0d620ae81973f104b43c9b7eaa789ad20ba4f6a1359f1cc62f63729a55a7d22d4e + languageName: node + linkType: hard + "@sindresorhus/slugify@npm:^2.1.1": version: 2.2.1 resolution: "@sindresorhus/slugify@npm:2.2.1" @@ -6947,6 +7141,15 @@ __metadata: languageName: node linkType: hard +"@types/chai@npm:^5.2.2": + version: 5.2.2 + resolution: "@types/chai@npm:5.2.2" + dependencies: + "@types/deep-eql": "npm:*" + checksum: 10c0/49282bf0e8246800ebb36f17256f97bd3a8c4fb31f92ad3c0eaa7623518d7e87f1eaad4ad206960fcaf7175854bdff4cb167e4fe96811e0081b4ada83dd533ec + languageName: node + linkType: hard + "@types/connect@npm:3.4.38": version: 3.4.38 resolution: "@types/connect@npm:3.4.38" @@ -7043,6 +7246,13 @@ __metadata: languageName: node linkType: hard +"@types/deep-eql@npm:*": + version: 4.0.2 + resolution: "@types/deep-eql@npm:4.0.2" + checksum: 10c0/bf3f811843117900d7084b9d0c852da9a044d12eb40e6de73b552598a6843c21291a8a381b0532644574beecd5e3491c5ff3a0365ab86b15d59862c025384844 + languageName: node + linkType: hard + "@types/deno@npm:^2.2.0": version: 2.3.0 resolution: "@types/deno@npm:2.3.0" @@ -7080,6 +7290,13 @@ __metadata: languageName: node linkType: hard +"@types/eventsource@npm:^1.1.15": + version: 1.1.15 + resolution: "@types/eventsource@npm:1.1.15" + checksum: 10c0/afee5c6c1185e365802349878411324569c77ae9878317b6e34bd633bdb5ee0a6eada6d1b358fec57640fe610eb43535344076db199895e1d9ab81511bb6ed0e + languageName: node + linkType: hard + "@types/extend@npm:^3.0.0": version: 3.0.4 resolution: "@types/extend@npm:3.0.4" @@ -7225,7 +7442,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:>=10.0.0, @types/node@npm:^22.13.1, @types/node@npm:^22.13.4, @types/node@npm:^22.13.9, @types/node@npm:^22.5.5": +"@types/node@npm:*, @types/node@npm:>=10.0.0, @types/node@npm:^22.13.4, @types/node@npm:^22.13.9, @types/node@npm:^22.5.5": version: 22.15.23 resolution: "@types/node@npm:22.15.23" dependencies: @@ -7241,6 +7458,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^20.11.19": + version: 20.19.0 + resolution: "@types/node@npm:20.19.0" + dependencies: + undici-types: "npm:~6.21.0" + checksum: 10c0/11979f5c4c626555351352fe1b30846700ca018747272a7ff425f883f102805b7f07737d5b7fa3c6deb0ddaeb94e367bb9a633a3d1e1d5c517de9a6283c6f21c + languageName: node + linkType: hard + "@types/node@npm:^20.11.30": version: 20.17.51 resolution: "@types/node@npm:20.17.51" @@ -7346,6 +7572,15 @@ __metadata: languageName: node linkType: hard +"@types/temp@npm:^0.9.4": + version: 0.9.4 + resolution: "@types/temp@npm:0.9.4" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/901fc8e7815b4bcdc47d1ed4273f13f2e3353ef57b33a81ee325e975989fbb32264f398a190b337360192b27b130eeceedfebd06a4eb195965affd3ff45698b7 + languageName: node + linkType: hard + "@types/trusted-types@npm:^2.0.2, @types/trusted-types@npm:^2.0.7": version: 2.0.7 resolution: "@types/trusted-types@npm:2.0.7" @@ -7544,6 +7779,17 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:1.6.1": + version: 1.6.1 + resolution: "@vitest/expect@npm:1.6.1" + dependencies: + "@vitest/spy": "npm:1.6.1" + "@vitest/utils": "npm:1.6.1" + chai: "npm:^4.3.10" + checksum: 10c0/278164b2a32a7019b443444f21111c5e32e4cadee026cae047ae2a3b347d99dca1d1fb7b79509c88b67dc3db19fa9a16265b7d7a8377485f7e37f7851e44495a + languageName: node + linkType: hard + "@vitest/expect@npm:3.1.4": version: 3.1.4 resolution: "@vitest/expect@npm:3.1.4" @@ -7556,6 +7802,19 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:3.2.3": + version: 3.2.3 + resolution: "@vitest/expect@npm:3.2.3" + dependencies: + "@types/chai": "npm:^5.2.2" + "@vitest/spy": "npm:3.2.3" + "@vitest/utils": "npm:3.2.3" + chai: "npm:^5.2.0" + tinyrainbow: "npm:^2.0.0" + checksum: 10c0/5eb6278be8f5294779472d1276e150a1b573274441a68c2681c447179abd22af451813fdfbe87e04f5909ca7a0926700f9b79022f227c9816e5d0fa8e0229e15 + languageName: node + linkType: hard + "@vitest/mocker@npm:3.1.4": version: 3.1.4 resolution: "@vitest/mocker@npm:3.1.4" @@ -7575,6 +7834,25 @@ __metadata: languageName: node linkType: hard +"@vitest/mocker@npm:3.2.3": + version: 3.2.3 + resolution: "@vitest/mocker@npm:3.2.3" + dependencies: + "@vitest/spy": "npm:3.2.3" + estree-walker: "npm:^3.0.3" + magic-string: "npm:^0.30.17" + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + checksum: 10c0/b670f229c3b1de5561de3cbbecb18f964d4888355d7f1cb8bbff4350b2cfbe477bef834cc2f66af7727ca7dc567540018885eb652f46e0be1cda4015491dc0a9 + languageName: node + linkType: hard + "@vitest/pretty-format@npm:3.1.4, @vitest/pretty-format@npm:^3.1.4": version: 3.1.4 resolution: "@vitest/pretty-format@npm:3.1.4" @@ -7584,6 +7862,26 @@ __metadata: languageName: node linkType: hard +"@vitest/pretty-format@npm:3.2.3, @vitest/pretty-format@npm:^3.2.3": + version: 3.2.3 + resolution: "@vitest/pretty-format@npm:3.2.3" + dependencies: + tinyrainbow: "npm:^2.0.0" + checksum: 10c0/e8fa7b97822c58404bef07d19fa9a49d5b7edb6797dd355584ad7246585bbbe9c55dd1fb05d0c3939b9c15fba05c3e134e2b96ea0cb64ca79a2b9dab60087a6a + languageName: node + linkType: hard + +"@vitest/runner@npm:1.6.1": + version: 1.6.1 + resolution: "@vitest/runner@npm:1.6.1" + dependencies: + "@vitest/utils": "npm:1.6.1" + p-limit: "npm:^5.0.0" + pathe: "npm:^1.1.1" + checksum: 10c0/36333f1a596c4ad85d42c6126cc32959c984d584ef28d366d366fa3672678c1a0f5e5c2e8717a36675b6620b57e8830f765d6712d1687f163ed0a8ebf23c87db + languageName: node + linkType: hard + "@vitest/runner@npm:3.1.4": version: 3.1.4 resolution: "@vitest/runner@npm:3.1.4" @@ -7594,6 +7892,28 @@ __metadata: languageName: node linkType: hard +"@vitest/runner@npm:3.2.3": + version: 3.2.3 + resolution: "@vitest/runner@npm:3.2.3" + dependencies: + "@vitest/utils": "npm:3.2.3" + pathe: "npm:^2.0.3" + strip-literal: "npm:^3.0.0" + checksum: 10c0/c20cb6e2ac4fdfb3d4f5136714ea65f9063562d3afaa1574dc82f53d061444bc01583f9915346768ca75f5ea0658f02fb594752e21abbca5ab50290f58732147 + languageName: node + linkType: hard + +"@vitest/snapshot@npm:1.6.1": + version: 1.6.1 + resolution: "@vitest/snapshot@npm:1.6.1" + dependencies: + magic-string: "npm:^0.30.5" + pathe: "npm:^1.1.1" + pretty-format: "npm:^29.7.0" + checksum: 10c0/68bbc3132c195ec37376469e4b183fc408e0aeedd827dffcc899aac378e9ea324825f0873062786e18f00e3da9dd8a93c9bb871c07471ee483e8df963cb272eb + languageName: node + linkType: hard + "@vitest/snapshot@npm:3.1.4": version: 3.1.4 resolution: "@vitest/snapshot@npm:3.1.4" @@ -7605,6 +7925,26 @@ __metadata: languageName: node linkType: hard +"@vitest/snapshot@npm:3.2.3": + version: 3.2.3 + resolution: "@vitest/snapshot@npm:3.2.3" + dependencies: + "@vitest/pretty-format": "npm:3.2.3" + magic-string: "npm:^0.30.17" + pathe: "npm:^2.0.3" + checksum: 10c0/f6dd0248afb3f3cbcbbb9fd39c2c8273c4ec92176f65e6ba9d36a0c33552d3658013e3a02944e14c7637f51d6702a5c07963b59707ca459bd1ac31f39c81160c + languageName: node + linkType: hard + +"@vitest/spy@npm:1.6.1": + version: 1.6.1 + resolution: "@vitest/spy@npm:1.6.1" + dependencies: + tinyspy: "npm:^2.2.0" + checksum: 10c0/5207ec0e7882819f0e0811293ae6d14163e26927e781bb4de7d40b3bd99c1fae656934c437bb7a30443a3e7e736c5bccb037bbf4436dbbc83d29e65247888885 + languageName: node + linkType: hard + "@vitest/spy@npm:3.1.4": version: 3.1.4 resolution: "@vitest/spy@npm:3.1.4" @@ -7614,6 +7954,27 @@ __metadata: languageName: node linkType: hard +"@vitest/spy@npm:3.2.3": + version: 3.2.3 + resolution: "@vitest/spy@npm:3.2.3" + dependencies: + tinyspy: "npm:^4.0.3" + checksum: 10c0/ce77d5934ac4741513993aad9d8ff44ff03ff5cf5a177e010c7ffcd8d3060087e56df1938c1100d49de712daf952cd2c72dd83e1684d043e698bd2afe0025f5e + languageName: node + linkType: hard + +"@vitest/utils@npm:1.6.1": + version: 1.6.1 + resolution: "@vitest/utils@npm:1.6.1" + dependencies: + diff-sequences: "npm:^29.6.3" + estree-walker: "npm:^3.0.3" + loupe: "npm:^2.3.7" + pretty-format: "npm:^29.7.0" + checksum: 10c0/0d4c619e5688cbc22a60c412719c6baa40376b7671bdbdc3072552f5c5a5ee5d24a96ea328b054018debd49e0626a5e3db672921b2c6b5b17b9a52edd296806a + languageName: node + linkType: hard + "@vitest/utils@npm:3.1.4": version: 3.1.4 resolution: "@vitest/utils@npm:3.1.4" @@ -7625,6 +7986,17 @@ __metadata: languageName: node linkType: hard +"@vitest/utils@npm:3.2.3": + version: 3.2.3 + resolution: "@vitest/utils@npm:3.2.3" + dependencies: + "@vitest/pretty-format": "npm:3.2.3" + loupe: "npm:^3.1.3" + tinyrainbow: "npm:^2.0.0" + checksum: 10c0/c7a785a73bc0d7c0202ced0d9912639b9deb6f05dd6c25700a13d97e13320ccec57660f11ad1f9225419ac485339fdf7af28c8d77456bcb9558e6c7d73ad538a + languageName: node + linkType: hard + "@volar/language-core@npm:1.11.1, @volar/language-core@npm:~1.11.1": version: 1.11.1 resolution: "@volar/language-core@npm:1.11.1" @@ -7770,7 +8142,7 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.1.1": +"acorn-walk@npm:^8.1.1, acorn-walk@npm:^8.3.2": version: 8.3.4 resolution: "acorn-walk@npm:8.3.4" dependencies: @@ -7788,10 +8160,11 @@ __metadata: languageName: node linkType: hard -"actor-core@portal:../actor-core/packages/actor-core::locator=rivet%40workspace%3A.": - version: 0.0.0-use.local - resolution: "actor-core@portal:../actor-core/packages/actor-core::locator=rivet%40workspace%3A." +"actor-core@npm:0.9.0-rc.1": + version: 0.9.0-rc.1 + resolution: "actor-core@npm:0.9.0-rc.1" dependencies: + "@hono/zod-openapi": "npm:^0.19.6" cbor-x: "npm:^1.6.0" hono: "npm:^4.7.0" invariant: "npm:^2.2.4" @@ -7808,8 +8181,32 @@ __metadata: optional: true bin: actor-core: ./dist/cli/mod.cjs + checksum: 10c0/07db1f0a783e53f25a7814da427203578748ca41ad5e35e648d071ad9e742dbe74eefd4f60e878aaa278de2e750def6f9b287d0942bed8928c8e7516bee06e18 languageName: node - linkType: soft + linkType: hard + +"actor-core@npm:^0.6.2": + version: 0.6.3 + resolution: "actor-core@npm:0.6.3" + dependencies: + cbor-x: "npm:^1.6.0" + hono: "npm:^4.7.0" + on-change: "npm:^5.0.1" + p-retry: "npm:^6.2.1" + zod: "npm:^3.24.1" + peerDependencies: + eventsource: ^3.0.5 + ws: ^8.0.0 + peerDependenciesMeta: + eventsource: + optional: true + ws: + optional: true + bin: + actor-core: ./dist/cli/mod.cjs + checksum: 10c0/4530252688961f39957cca6f6ac2edfd1a6a52f8dac0cc8cebff23a170084089fb56180e0041f2c458681d8033c3205aa4467f10c8da0c4297777153528dcebd + languageName: node + linkType: hard "agent-base@npm:6": version: 6.0.2 @@ -7900,6 +8297,13 @@ __metadata: languageName: node linkType: hard +"ansi-styles@npm:^5.0.0": + version: 5.2.0 + resolution: "ansi-styles@npm:5.2.0" + checksum: 10c0/9c4ca80eb3c2fb7b33841c210d2f20807f40865d27008d7c3f707b7f95cab7d67462a565e2388ac3285b71cb3d9bb2173de8da37c57692a362885ec34d6e27df + languageName: node + linkType: hard + "ansi-styles@npm:^6.1.0": version: 6.2.1 resolution: "ansi-styles@npm:6.2.1" @@ -8089,6 +8493,13 @@ __metadata: languageName: node linkType: hard +"assertion-error@npm:^1.1.0": + version: 1.1.0 + resolution: "assertion-error@npm:1.1.0" + checksum: 10c0/25456b2aa333250f01143968e02e4884a34588a8538fbbf65c91a637f1dbfb8069249133cd2f4e530f10f624d206a664e7df30207830b659e9f5298b00a4099b + languageName: node + linkType: hard + "assertion-error@npm:^2.0.1": version: 2.0.1 resolution: "assertion-error@npm:2.0.1" @@ -8170,7 +8581,7 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.5.0": +"axios@npm:^1.5.0, axios@npm:^1.6.7": version: 1.9.0 resolution: "axios@npm:1.9.0" dependencies: @@ -8586,9 +8997,24 @@ __metadata: languageName: node linkType: hard -"chai@npm:^5.2.0": - version: 5.2.0 - resolution: "chai@npm:5.2.0" +"chai@npm:^4.3.10": + version: 4.5.0 + resolution: "chai@npm:4.5.0" + dependencies: + assertion-error: "npm:^1.1.0" + check-error: "npm:^1.0.3" + deep-eql: "npm:^4.1.3" + get-func-name: "npm:^2.0.2" + loupe: "npm:^2.3.6" + pathval: "npm:^1.1.1" + type-detect: "npm:^4.1.0" + checksum: 10c0/b8cb596bd1aece1aec659e41a6e479290c7d9bee5b3ad63d2898ad230064e5b47889a3bc367b20100a0853b62e026e2dc514acf25a3c9385f936aa3614d4ab4d + languageName: node + linkType: hard + +"chai@npm:^5.2.0": + version: 5.2.0 + resolution: "chai@npm:5.2.0" dependencies: assertion-error: "npm:^2.0.1" check-error: "npm:^2.1.1" @@ -8680,6 +9106,15 @@ __metadata: languageName: node linkType: hard +"check-error@npm:^1.0.3": + version: 1.0.3 + resolution: "check-error@npm:1.0.3" + dependencies: + get-func-name: "npm:^2.0.2" + checksum: 10c0/94aa37a7315c0e8a83d0112b5bfb5a8624f7f0f81057c73e4707729cdd8077166c6aefb3d8e2b92c63ee130d4a2ff94bad46d547e12f3238cc1d78342a973841 + languageName: node + linkType: hard + "check-error@npm:^2.1.1": version: 2.1.1 resolution: "check-error@npm:2.1.1" @@ -8729,6 +9164,28 @@ __metadata: languageName: node linkType: hard +"ci-manager@workspace:cloud/packages/ci-manager": + version: 0.0.0-use.local + resolution: "ci-manager@workspace:cloud/packages/ci-manager" + dependencies: + "@hono/node-server": "npm:^1.14.4" + "@rivet-gg/api": "npm:^25.4.2" + "@types/eventsource": "npm:^1.1.15" + eventsource: "npm:^4.0.0" + get-port: "npm:^7.1.0" + hono: "npm:^4.7.11" + nanoevents: "npm:^9.1.0" + tar: "npm:^7.4.3" + tsx: "npm:^4.19.4" + typescript: "npm:^5.7.2" + vitest: "npm:^3.2.2" + zod: "npm:^3.25.56" + zx: "npm:^8.1.9" + peerDependencies: + typescript: ^5 + languageName: unknown + linkType: soft + "cjs-module-lexer@npm:^1.2.2": version: 1.4.3 resolution: "cjs-module-lexer@npm:1.4.3" @@ -8988,7 +9445,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.6": +"cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -9185,7 +9642,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.3.7, debug@npm:^4.4.0": +"debug@npm:4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.3.7, debug@npm:^4.4.0, debug@npm:^4.4.1": version: 4.4.1 resolution: "debug@npm:4.4.1" dependencies: @@ -9255,6 +9712,15 @@ __metadata: languageName: node linkType: hard +"deep-eql@npm:^4.1.3": + version: 4.1.4 + resolution: "deep-eql@npm:4.1.4" + dependencies: + type-detect: "npm:^4.0.0" + checksum: 10c0/264e0613493b43552fc908f4ff87b8b445c0e6e075656649600e1b8a17a57ee03e960156fce7177646e4d2ddaf8e5ee616d76bd79929ff593e5c79e4e5e6c517 + languageName: node + linkType: hard + "deep-eql@npm:^5.0.1": version: 5.0.2 resolution: "deep-eql@npm:5.0.2" @@ -9387,6 +9853,13 @@ __metadata: languageName: node linkType: hard +"diff-sequences@npm:^29.6.3": + version: 29.6.3 + resolution: "diff-sequences@npm:29.6.3" + checksum: 10c0/32e27ac7dbffdf2fb0eb5a84efd98a9ad084fbabd5ac9abb8757c6770d5320d2acd172830b28c4add29bb873d59420601dfc805ac4064330ce59b1adfd0593b2 + languageName: node + linkType: hard + "diff@npm:^4.0.1": version: 4.0.2 resolution: "diff@npm:4.0.2" @@ -10506,6 +10979,22 @@ __metadata: languageName: node linkType: hard +"eventsource-parser@npm:^3.0.1": + version: 3.0.2 + resolution: "eventsource-parser@npm:3.0.2" + checksum: 10c0/067c6e60b7c68a4577630cc7e11d2aaeef52005e377a213308c7c2350596a175d5a179671d85f570726dce3f451c15d174ece4479ce68a1805686c88950d08dd + languageName: node + linkType: hard + +"eventsource@npm:^4.0.0": + version: 4.0.0 + resolution: "eventsource@npm:4.0.0" + dependencies: + eventsource-parser: "npm:^3.0.1" + checksum: 10c0/908a3f64b60aadd053b9fd8ea8b6a896a4faf32dbbaf0150e91abbec179a9e2a3da261fb577ae296df8b744de91962d69a60b10e8d7092d7802e6e3e7a8b0f0e + languageName: node + linkType: hard + "example-functions@workspace:examples/functions-js": version: 0.0.0-use.local resolution: "example-functions@workspace:examples/functions-js" @@ -10524,6 +11013,23 @@ __metadata: languageName: unknown linkType: soft +"execa@npm:^8.0.1": + version: 8.0.1 + resolution: "execa@npm:8.0.1" + dependencies: + cross-spawn: "npm:^7.0.3" + get-stream: "npm:^8.0.1" + human-signals: "npm:^5.0.0" + is-stream: "npm:^3.0.0" + merge-stream: "npm:^2.0.0" + npm-run-path: "npm:^5.1.0" + onetime: "npm:^6.0.0" + signal-exit: "npm:^4.1.0" + strip-final-newline: "npm:^3.0.0" + checksum: 10c0/2c52d8775f5bf103ce8eec9c7ab3059909ba350a5164744e9947ed14a53f51687c040a250bda833f906d1283aa8803975b84e6c8f7a7c42f99dc8ef80250d1af + languageName: node + linkType: hard + "expand-template@npm:^2.0.3": version: 2.0.3 resolution: "expand-template@npm:2.0.3" @@ -10980,6 +11486,13 @@ __metadata: languageName: node linkType: hard +"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": + version: 2.0.2 + resolution: "get-func-name@npm:2.0.2" + checksum: 10c0/89830fd07623fa73429a711b9daecdb304386d237c71268007f788f113505ef1d4cc2d0b9680e072c5082490aec9df5d7758bf5ac6f1c37062855e8e3dc0b9df + languageName: node + linkType: hard + "get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.2.7, get-intrinsic@npm:^1.3.0": version: 1.3.0 resolution: "get-intrinsic@npm:1.3.0" @@ -11005,6 +11518,13 @@ __metadata: languageName: node linkType: hard +"get-port@npm:^7.1.0": + version: 7.1.0 + resolution: "get-port@npm:7.1.0" + checksum: 10c0/896051fea0fd3df58c050566754ab91f46406e898ce0c708414739d908a5ac03ffef3eca7a494ea9cc1914439e8caccd2218010d1eeabdde914b9ff920fa28fc + languageName: node + linkType: hard + "get-proto@npm:^1.0.0, get-proto@npm:^1.0.1": version: 1.0.1 resolution: "get-proto@npm:1.0.1" @@ -11015,6 +11535,13 @@ __metadata: languageName: node linkType: hard +"get-stream@npm:^8.0.1": + version: 8.0.1 + resolution: "get-stream@npm:8.0.1" + checksum: 10c0/5c2181e98202b9dae0bb4a849979291043e5892eb40312b47f0c22b9414fc9b28a3b6063d2375705eb24abc41ecf97894d9a51f64ff021511b504477b27b4290 + languageName: node + linkType: hard + "get-stream@npm:^9.0.1": version: 9.0.1 resolution: "get-stream@npm:9.0.1" @@ -11521,6 +12048,13 @@ __metadata: languageName: node linkType: hard +"hono@npm:^4.0.5, hono@npm:^4.7.11": + version: 4.7.11 + resolution: "hono@npm:4.7.11" + checksum: 10c0/2821471b09f2e9f7bab5ad7412e2e44df5f07b7098508d70dd6e368b933580f03a06c30e20dd764b53e0121e1b1ff2132ae98cffa7fd1b286e299f9054effd6a + languageName: node + linkType: hard + "hono@npm:^4.6.16, hono@npm:^4.6.17, hono@npm:^4.7.0, hono@npm:^4.7.2": version: 4.7.10 resolution: "hono@npm:4.7.10" @@ -11579,6 +12113,13 @@ __metadata: languageName: node linkType: hard +"human-signals@npm:^5.0.0": + version: 5.0.0 + resolution: "human-signals@npm:5.0.0" + checksum: 10c0/5a9359073fe17a8b58e5a085e9a39a950366d9f00217c4ff5878bd312e09d80f460536ea6a3f260b5943a01fe55c158d1cea3fc7bee3d0520aeef04f6d915c82 + languageName: node + linkType: hard + "iconv-lite@npm:^0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" @@ -12021,6 +12562,13 @@ __metadata: languageName: node linkType: hard +"is-stream@npm:^3.0.0": + version: 3.0.0 + resolution: "is-stream@npm:3.0.0" + checksum: 10c0/eb2f7127af02ee9aa2a0237b730e47ac2de0d4e76a4a905a50a11557f2339df5765eaea4ceb8029f1efa978586abe776908720bfcb1900c20c6ec5145f6f29d8 + languageName: node + linkType: hard + "is-stream@npm:^4.0.1": version: 4.0.1 resolution: "is-stream@npm:4.0.1" @@ -12270,6 +12818,13 @@ __metadata: languageName: node linkType: hard +"js-tokens@npm:^9.0.1": + version: 9.0.1 + resolution: "js-tokens@npm:9.0.1" + checksum: 10c0/68dcab8f233dde211a6b5fd98079783cbcd04b53617c1250e3553ee16ab3e6134f5e65478e41d82f6d351a052a63d71024553933808570f04dbf828d7921e80e + languageName: node + linkType: hard + "js-yaml@npm:^4.1.0": version: 4.1.0 resolution: "js-yaml@npm:4.1.0" @@ -12633,6 +13188,15 @@ __metadata: languageName: node linkType: hard +"loupe@npm:^2.3.6, loupe@npm:^2.3.7": + version: 2.3.7 + resolution: "loupe@npm:2.3.7" + dependencies: + get-func-name: "npm:^2.0.1" + checksum: 10c0/71a781c8fc21527b99ed1062043f1f2bb30bdaf54fa4cf92463427e1718bc6567af2988300bc243c1f276e4f0876f29e3cbf7b58106fdc186915687456ce5bf4 + languageName: node + linkType: hard + "loupe@npm:^3.1.0, loupe@npm:^3.1.3": version: 3.1.3 resolution: "loupe@npm:3.1.3" @@ -12683,7 +13247,7 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.17, magic-string@npm:^0.30.8": +"magic-string@npm:^0.30.17, magic-string@npm:^0.30.5, magic-string@npm:^0.30.8": version: 0.30.17 resolution: "magic-string@npm:0.30.17" dependencies: @@ -13056,6 +13620,13 @@ __metadata: languageName: node linkType: hard +"merge-stream@npm:^2.0.0": + version: 2.0.0 + resolution: "merge-stream@npm:2.0.0" + checksum: 10c0/867fdbb30a6d58b011449b8885601ec1690c3e41c759ecd5a9d609094f7aed0096c37823ff4a7190ef0b8f22cc86beb7049196ff68c016e3b3c671d0dac91ce5 + languageName: node + linkType: hard + "merge2@npm:^1.3.0, merge2@npm:^1.4.1": version: 1.4.1 resolution: "merge2@npm:1.4.1" @@ -13580,6 +14151,13 @@ __metadata: languageName: node linkType: hard +"mimic-fn@npm:^4.0.0": + version: 4.0.0 + resolution: "mimic-fn@npm:4.0.0" + checksum: 10c0/de9cc32be9996fd941e512248338e43407f63f6d497abe8441fa33447d922e927de54d4cc3c1a3c6d652857acd770389d5a3823f311a744132760ce2be15ccbf + languageName: node + linkType: hard + "mimic-response@npm:^3.1.0": version: 3.1.0 resolution: "mimic-response@npm:3.1.0" @@ -13729,6 +14307,17 @@ __metadata: languageName: node linkType: hard +"mkdirp@npm:^0.5.1": + version: 0.5.6 + resolution: "mkdirp@npm:0.5.6" + dependencies: + minimist: "npm:^1.2.6" + bin: + mkdirp: bin/cmd.js + checksum: 10c0/e2e2be789218807b58abced04e7b49851d9e46e88a2f9539242cc8a92c9b5c3a0b9bab360bd3014e02a140fc4fbc58e31176c408b493f8a2a6f4986bd7527b01 + languageName: node + linkType: hard + "mkdirp@npm:^3.0.1": version: 3.0.1 resolution: "mkdirp@npm:3.0.1" @@ -13814,6 +14403,23 @@ __metadata: languageName: node linkType: hard +"multitenant-deploys@workspace:examples/multitenant-deploys": + version: 0.0.0-use.local + resolution: "multitenant-deploys@workspace:examples/multitenant-deploys" + dependencies: + "@hono/node-server": "npm:^1.7.0" + "@rivet-gg/api-full": "workspace:*" + "@types/node": "npm:^20.11.19" + "@types/temp": "npm:^0.9.4" + axios: "npm:^1.6.7" + hono: "npm:^4.0.5" + temp: "npm:^0.9.4" + tsx: "npm:^4.7.0" + typescript: "npm:^5.3.3" + vitest: "npm:^1.2.2" + languageName: unknown + linkType: soft + "mute-stream@npm:^1.0.0": version: 1.0.0 resolution: "mute-stream@npm:1.0.0" @@ -13832,6 +14438,13 @@ __metadata: languageName: node linkType: hard +"nanoevents@npm:^9.1.0": + version: 9.1.0 + resolution: "nanoevents@npm:9.1.0" + checksum: 10c0/5fb48e6fc1d3102daddaeffd6eada907c25b1c8554dcc648e9cb0a72979a1ab3ee56ffa2d2b3e566a8e561a9e2992a3783493c61cfaaa096b2986d56dbbc1ca5 + languageName: node + linkType: hard + "nanoid@npm:^3.3.6, nanoid@npm:^3.3.8": version: 3.3.11 resolution: "nanoid@npm:3.3.11" @@ -14064,6 +14677,15 @@ __metadata: languageName: node linkType: hard +"npm-run-path@npm:^5.1.0": + version: 5.3.0 + resolution: "npm-run-path@npm:5.3.0" + dependencies: + path-key: "npm:^4.0.0" + checksum: 10c0/124df74820c40c2eb9a8612a254ea1d557ddfab1581c3e751f825e3e366d9f00b0d76a3c94ecd8398e7f3eee193018622677e95816e8491f0797b21e30b2deba + languageName: node + linkType: hard + "oauth4webapi@npm:^3.5.1": version: 3.5.1 resolution: "oauth4webapi@npm:3.5.1" @@ -14190,6 +14812,15 @@ __metadata: languageName: node linkType: hard +"onetime@npm:^6.0.0": + version: 6.0.0 + resolution: "onetime@npm:6.0.0" + dependencies: + mimic-fn: "npm:^4.0.0" + checksum: 10c0/4eef7c6abfef697dd4479345a4100c382d73c149d2d56170a54a07418c50816937ad09500e1ed1e79d235989d073a9bade8557122aee24f0576ecde0f392bb6c + languageName: node + linkType: hard + "oniguruma-to-es@npm:^2.2.0": version: 2.3.0 resolution: "oniguruma-to-es@npm:2.3.0" @@ -14224,6 +14855,15 @@ __metadata: languageName: node linkType: hard +"openapi3-ts@npm:^4.1.2": + version: 4.4.0 + resolution: "openapi3-ts@npm:4.4.0" + dependencies: + yaml: "npm:^2.5.0" + checksum: 10c0/900b834279fc8a43c545728ad75ec7c26934ec5344225b60d1e1c0df44d742d7e7379aea18d9034e03031f079d3308ba5a68600682eece3ed41cdbdd10346a9e + languageName: node + linkType: hard + "openid-client@npm:^6.5.0": version: 6.5.0 resolution: "openid-client@npm:6.5.0" @@ -14282,6 +14922,15 @@ __metadata: languageName: node linkType: hard +"p-limit@npm:^5.0.0": + version: 5.0.0 + resolution: "p-limit@npm:5.0.0" + dependencies: + yocto-queue: "npm:^1.0.0" + checksum: 10c0/574e93b8895a26e8485eb1df7c4b58a1a6e8d8ae41b1750cc2cc440922b3d306044fc6e9a7f74578a883d46802d9db72b30f2e612690fcef838c173261b1ed83 + languageName: node + linkType: hard + "p-locate@npm:^5.0.0": version: 5.0.0 resolution: "p-locate@npm:5.0.0" @@ -14394,6 +15043,13 @@ __metadata: languageName: node linkType: hard +"path-key@npm:^4.0.0": + version: 4.0.0 + resolution: "path-key@npm:4.0.0" + checksum: 10c0/794efeef32863a65ac312f3c0b0a99f921f3e827ff63afa5cb09a377e202c262b671f7b3832a4e64731003fa94af0263713962d317b9887bd1e0c48a342efba3 + languageName: node + linkType: hard + "path-parse@npm:^1.0.6, path-parse@npm:^1.0.7": version: 1.0.7 resolution: "path-parse@npm:1.0.7" @@ -14418,7 +15074,7 @@ __metadata: languageName: node linkType: hard -"pathe@npm:^1.1.2": +"pathe@npm:^1.1.1, pathe@npm:^1.1.2": version: 1.1.2 resolution: "pathe@npm:1.1.2" checksum: 10c0/64ee0a4e587fb0f208d9777a6c56e4f9050039268faaaaecd50e959ef01bf847b7872785c36483fa5cdcdbdfdb31fef2ff222684d4fc21c330ab60395c681897 @@ -14432,6 +15088,13 @@ __metadata: languageName: node linkType: hard +"pathval@npm:^1.1.1": + version: 1.1.1 + resolution: "pathval@npm:1.1.1" + checksum: 10c0/f63e1bc1b33593cdf094ed6ff5c49c1c0dc5dc20a646ca9725cc7fe7cd9995002d51d5685b9b2ec6814342935748b711bafa840f84c0bb04e38ff40a335c94dc + languageName: node + linkType: hard + "pathval@npm:^2.0.0": version: 2.0.0 resolution: "pathval@npm:2.0.0" @@ -14893,6 +15556,17 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:^29.7.0": + version: 29.7.0 + resolution: "pretty-format@npm:29.7.0" + dependencies: + "@jest/schemas": "npm:^29.6.3" + ansi-styles: "npm:^5.0.0" + react-is: "npm:^18.0.0" + checksum: 10c0/edc5ff89f51916f036c62ed433506b55446ff739358de77207e63e88a28ca2894caac6e73dcb68166a606e51c8087d32d400473e6a9fdd2dbe743f46c9c0276f + languageName: node + linkType: hard + "proc-log@npm:^5.0.0": version: 5.0.0 resolution: "proc-log@npm:5.0.0" @@ -15116,7 +15790,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^18.3.1": +"react-is@npm:^18.0.0, react-is@npm:^18.3.1": version: 18.3.1 resolution: "react-is@npm:18.3.1" checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072 @@ -15819,6 +16493,17 @@ __metadata: languageName: node linkType: hard +"rimraf@npm:~2.6.2": + version: 2.6.3 + resolution: "rimraf@npm:2.6.3" + dependencies: + glob: "npm:^7.1.3" + bin: + rimraf: ./bin.js + checksum: 10c0/f1e646f8c567795f2916aef7aadf685b543da6b9a53e482bb04b07472c7eef2b476045ba1e29f401c301c66b630b22b815ab31fdd60c5e1ae6566ff523debf45 + languageName: node + linkType: hard + "rivet-site@workspace:site": version: 0.0.0-use.local resolution: "rivet-site@workspace:site" @@ -16010,6 +16695,81 @@ __metadata: languageName: node linkType: hard +"rollup@npm:^4.40.0": + version: 4.42.0 + resolution: "rollup@npm:4.42.0" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.42.0" + "@rollup/rollup-android-arm64": "npm:4.42.0" + "@rollup/rollup-darwin-arm64": "npm:4.42.0" + "@rollup/rollup-darwin-x64": "npm:4.42.0" + "@rollup/rollup-freebsd-arm64": "npm:4.42.0" + "@rollup/rollup-freebsd-x64": "npm:4.42.0" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.42.0" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.42.0" + "@rollup/rollup-linux-arm64-gnu": "npm:4.42.0" + "@rollup/rollup-linux-arm64-musl": "npm:4.42.0" + "@rollup/rollup-linux-loongarch64-gnu": "npm:4.42.0" + "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.42.0" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.42.0" + "@rollup/rollup-linux-riscv64-musl": "npm:4.42.0" + "@rollup/rollup-linux-s390x-gnu": "npm:4.42.0" + "@rollup/rollup-linux-x64-gnu": "npm:4.42.0" + "@rollup/rollup-linux-x64-musl": "npm:4.42.0" + "@rollup/rollup-win32-arm64-msvc": "npm:4.42.0" + "@rollup/rollup-win32-ia32-msvc": "npm:4.42.0" + "@rollup/rollup-win32-x64-msvc": "npm:4.42.0" + "@types/estree": "npm:1.0.7" + fsevents: "npm:~2.3.2" + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-freebsd-arm64": + optional: true + "@rollup/rollup-freebsd-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-loongarch64-gnu": + optional: true + "@rollup/rollup-linux-powerpc64le-gnu": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-riscv64-musl": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 10c0/160fdb0874af5f0f619987b4e9abb3b136fc154f759762bfde4d65d864d6d06594ae7d1d8e6d4558d1b8ef329aaa6a8de543e90feead3d872db15cf61f78426c + languageName: node + linkType: hard + "run-applescript@npm:^7.0.0": version: 7.0.0 resolution: "run-applescript@npm:7.0.0" @@ -16691,7 +17451,7 @@ __metadata: languageName: node linkType: hard -"std-env@npm:^3.9.0": +"std-env@npm:^3.5.0, std-env@npm:^3.9.0": version: 3.9.0 resolution: "std-env@npm:3.9.0" checksum: 10c0/4a6f9218aef3f41046c3c7ecf1f98df00b30a07f4f35c6d47b28329bc2531eef820828951c7d7b39a1c5eb19ad8a46e3ddfc7deb28f0a2f3ceebee11bab7ba50 @@ -16872,6 +17632,13 @@ __metadata: languageName: node linkType: hard +"strip-final-newline@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-final-newline@npm:3.0.0" + checksum: 10c0/a771a17901427bac6293fd416db7577e2bc1c34a19d38351e9d5478c3c415f523f391003b42ed475f27e33a78233035df183525395f731d3bfb8cdcbd4da08ce + languageName: node + linkType: hard + "strip-json-comments@npm:^3.1.0, strip-json-comments@npm:^3.1.1, strip-json-comments@npm:~3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" @@ -16886,6 +17653,24 @@ __metadata: languageName: node linkType: hard +"strip-literal@npm:^2.0.0": + version: 2.1.1 + resolution: "strip-literal@npm:2.1.1" + dependencies: + js-tokens: "npm:^9.0.1" + checksum: 10c0/66a7353f5ba1ae6a4fb2805b4aba228171847200640083117c41512692e6b2c020e18580402984f55c0ae69c30f857f9a55abd672863e4ca8fdb463fdf93ba19 + languageName: node + linkType: hard + +"strip-literal@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-literal@npm:3.0.0" + dependencies: + js-tokens: "npm:^9.0.1" + checksum: 10c0/d81657f84aba42d4bbaf2a677f7e7f34c1f3de5a6726db8bc1797f9c0b303ba54d4660383a74bde43df401cf37cce1dff2c842c55b077a4ceee11f9e31fba828 + languageName: node + linkType: hard + "strnum@npm:^1.0.5": version: 1.1.2 resolution: "strnum@npm:1.1.2" @@ -17025,7 +17810,6 @@ __metadata: "@hono/node-server": "npm:^1.13.8" "@hono/node-ws": "npm:^1.1.0" "@rivet-gg/actor-core": "npm:^5.1.2" - "@rivet-gg/api-full": "workspace:*" "@types/deno": "npm:^2.2.0" "@types/node": "npm:^22.13.9" "@types/ws": "npm:^8.18.0" @@ -17160,6 +17944,16 @@ __metadata: languageName: node linkType: hard +"temp@npm:^0.9.4": + version: 0.9.4 + resolution: "temp@npm:0.9.4" + dependencies: + mkdirp: "npm:^0.5.1" + rimraf: "npm:~2.6.2" + checksum: 10c0/7a1cd75efa65b9ca97fc0dfa752673842d23fa41d9c641a447d86ca986eb7662f0d17771e1edf8d0149e76de3c6e7005faf2ccaa3baf64811c86d1d1a951dda7 + languageName: node + linkType: hard + "text-decoder@npm:^1.1.0": version: 1.2.3 resolution: "text-decoder@npm:1.2.3" @@ -17222,7 +18016,7 @@ __metadata: languageName: node linkType: hard -"tinybench@npm:^2.9.0": +"tinybench@npm:^2.5.1, tinybench@npm:^2.9.0": version: 2.9.0 resolution: "tinybench@npm:2.9.0" checksum: 10c0/c3500b0f60d2eb8db65250afe750b66d51623057ee88720b7f064894a6cb7eb93360ca824a60a31ab16dab30c7b1f06efe0795b352e37914a9d4bad86386a20c @@ -17236,7 +18030,7 @@ __metadata: languageName: node linkType: hard -"tinyglobby@npm:^0.2.11, tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.13": +"tinyglobby@npm:^0.2.11, tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.13, tinyglobby@npm:^0.2.14": version: 0.2.14 resolution: "tinyglobby@npm:0.2.14" dependencies: @@ -17246,6 +18040,13 @@ __metadata: languageName: node linkType: hard +"tinypool@npm:^0.8.3": + version: 0.8.4 + resolution: "tinypool@npm:0.8.4" + checksum: 10c0/779c790adcb0316a45359652f4b025958c1dff5a82460fe49f553c864309b12ad732c8288be52f852973bc76317f5e7b3598878aee0beb8a33322c0e72c4a66c + languageName: node + linkType: hard + "tinypool@npm:^1.0.2": version: 1.0.2 resolution: "tinypool@npm:1.0.2" @@ -17253,6 +18054,13 @@ __metadata: languageName: node linkType: hard +"tinypool@npm:^1.1.0": + version: 1.1.0 + resolution: "tinypool@npm:1.1.0" + checksum: 10c0/deb6bde5e3d85d4ba043806c66f43fb5b649716312a47b52761a83668ffc71cd0ea4e24254c1b02a3702e5c27e02605f0189a1460f6284a5930a08bd0c06435c + languageName: node + linkType: hard + "tinyrainbow@npm:^2.0.0": version: 2.0.0 resolution: "tinyrainbow@npm:2.0.0" @@ -17260,6 +18068,13 @@ __metadata: languageName: node linkType: hard +"tinyspy@npm:^2.2.0": + version: 2.2.1 + resolution: "tinyspy@npm:2.2.1" + checksum: 10c0/0b4cfd07c09871e12c592dfa7b91528124dc49a4766a0b23350638c62e6a483d5a2a667de7e6282246c0d4f09996482ddaacbd01f0c05b7ed7e0f79d32409bdc + languageName: node + linkType: hard + "tinyspy@npm:^3.0.2": version: 3.0.2 resolution: "tinyspy@npm:3.0.2" @@ -17267,6 +18082,13 @@ __metadata: languageName: node linkType: hard +"tinyspy@npm:^4.0.3": + version: 4.0.3 + resolution: "tinyspy@npm:4.0.3" + checksum: 10c0/0a92a18b5350945cc8a1da3a22c9ad9f4e2945df80aaa0c43e1b3a3cfb64d8501e607ebf0305e048e3c3d3e0e7f8eb10cea27dc17c21effb73e66c4a3be36373 + languageName: node + linkType: hard + "tmp@npm:^0.0.33": version: 0.0.33 resolution: "tmp@npm:0.0.33" @@ -17472,7 +18294,7 @@ __metadata: languageName: node linkType: hard -"tsx@npm:^4.19.2, tsx@npm:^4.19.3, tsx@npm:^4.7.0": +"tsx@npm:^4.19.2, tsx@npm:^4.19.3, tsx@npm:^4.19.4, tsx@npm:^4.7.0": version: 4.19.4 resolution: "tsx@npm:4.19.4" dependencies: @@ -17584,6 +18406,13 @@ __metadata: languageName: node linkType: hard +"type-detect@npm:^4.0.0, type-detect@npm:^4.1.0": + version: 4.1.0 + resolution: "type-detect@npm:4.1.0" + checksum: 10c0/df8157ca3f5d311edc22885abc134e18ff8ffbc93d6a9848af5b682730ca6a5a44499259750197250479c5331a8a75b5537529df5ec410622041650a7f293e2a + languageName: node + linkType: hard + "type-fest@npm:^0.20.2": version: 0.20.2 resolution: "type-fest@npm:0.20.2" @@ -17678,7 +18507,7 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.1.6, typescript@npm:^5.3.3, typescript@npm:^5.5.4, typescript@npm:^5.7.3": +"typescript@npm:^5.1.6, typescript@npm:^5.3.3, typescript@npm:^5.5.4, typescript@npm:^5.7.2, typescript@npm:^5.7.3": version: 5.8.3 resolution: "typescript@npm:5.8.3" bin: @@ -17708,7 +18537,7 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^5.1.6#optional!builtin, typescript@patch:typescript@npm%3A^5.3.3#optional!builtin, typescript@patch:typescript@npm%3A^5.5.4#optional!builtin, typescript@patch:typescript@npm%3A^5.7.3#optional!builtin": +"typescript@patch:typescript@npm%3A^5.1.6#optional!builtin, typescript@patch:typescript@npm%3A^5.3.3#optional!builtin, typescript@patch:typescript@npm%3A^5.5.4#optional!builtin, typescript@patch:typescript@npm%3A^5.7.2#optional!builtin, typescript@patch:typescript@npm%3A^5.7.3#optional!builtin": version: 5.8.3 resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5" bin: @@ -18213,6 +19042,21 @@ __metadata: languageName: node linkType: hard +"vite-node@npm:1.6.1": + version: 1.6.1 + resolution: "vite-node@npm:1.6.1" + dependencies: + cac: "npm:^6.7.14" + debug: "npm:^4.3.4" + pathe: "npm:^1.1.1" + picocolors: "npm:^1.0.0" + vite: "npm:^5.0.0" + bin: + vite-node: vite-node.mjs + checksum: 10c0/4d96da9f11bd0df8b60c46e65a740edaad7dd2d1aff3cdb3da5714ea8c10b5f2683111b60bfe45545c7e8c1f33e7e8a5095573d5e9ba55f50a845233292c2e02 + languageName: node + linkType: hard + "vite-node@npm:3.1.4": version: 3.1.4 resolution: "vite-node@npm:3.1.4" @@ -18228,6 +19072,21 @@ __metadata: languageName: node linkType: hard +"vite-node@npm:3.2.3": + version: 3.2.3 + resolution: "vite-node@npm:3.2.3" + dependencies: + cac: "npm:^6.7.14" + debug: "npm:^4.4.1" + es-module-lexer: "npm:^1.7.0" + pathe: "npm:^2.0.3" + vite: "npm:^5.0.0 || ^6.0.0 || ^7.0.0-0" + bin: + vite-node: vite-node.mjs + checksum: 10c0/b952b0d9e45662506ea7303ac87d08e02f1e3355777cf7d426f211292c4f87e8837aef589e552bb11404d1bc0a9bd18871ce6ba874b5f0bb171f8e010de20a11 + languageName: node + linkType: hard + "vite-node@npm:^2.1.1": version: 2.1.9 resolution: "vite-node@npm:2.1.9" @@ -18328,6 +19187,61 @@ __metadata: languageName: node linkType: hard +"vite@npm:^5.0.0 || ^6.0.0 || ^7.0.0-0": + version: 7.0.0-beta.0 + resolution: "vite@npm:7.0.0-beta.0" + dependencies: + esbuild: "npm:^0.25.0" + fdir: "npm:^6.4.4" + fsevents: "npm:~2.3.3" + picomatch: "npm:^4.0.2" + postcss: "npm:^8.5.3" + rollup: "npm:^4.40.0" + tinyglobby: "npm:^0.2.14" + peerDependencies: + "@types/node": ^20.19.0 || >=22.12.0 + jiti: ">=1.21.0" + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: ">=0.54.8" + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + bin: + vite: bin/vite.js + checksum: 10c0/d13907d67b4991a2862dafe6a31d10ffe28f26ba04e511049e9d86d06293b3a8d6733c896c8fb38e3f2d5805d240e3cad27700f3c42536602035e4c324b48d58 + languageName: node + linkType: hard + "vite@npm:^5.0.0, vite@npm:^5.2.0": version: 5.4.19 resolution: "vite@npm:5.4.19" @@ -18371,6 +19285,56 @@ __metadata: languageName: node linkType: hard +"vitest@npm:^1.2.2": + version: 1.6.1 + resolution: "vitest@npm:1.6.1" + dependencies: + "@vitest/expect": "npm:1.6.1" + "@vitest/runner": "npm:1.6.1" + "@vitest/snapshot": "npm:1.6.1" + "@vitest/spy": "npm:1.6.1" + "@vitest/utils": "npm:1.6.1" + acorn-walk: "npm:^8.3.2" + chai: "npm:^4.3.10" + debug: "npm:^4.3.4" + execa: "npm:^8.0.1" + local-pkg: "npm:^0.5.0" + magic-string: "npm:^0.30.5" + pathe: "npm:^1.1.1" + picocolors: "npm:^1.0.0" + std-env: "npm:^3.5.0" + strip-literal: "npm:^2.0.0" + tinybench: "npm:^2.5.1" + tinypool: "npm:^0.8.3" + vite: "npm:^5.0.0" + vite-node: "npm:1.6.1" + why-is-node-running: "npm:^2.2.2" + peerDependencies: + "@edge-runtime/vm": "*" + "@types/node": ^18.0.0 || >=20.0.0 + "@vitest/browser": 1.6.1 + "@vitest/ui": 1.6.1 + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@types/node": + optional: true + "@vitest/browser": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + bin: + vitest: vitest.mjs + checksum: 10c0/511d27d7f697683964826db2fad7ac303f9bc7eeb59d9422111dc488371ccf1f9eed47ac3a80eb47ca86b7242228ba5ca9cc3613290830d0e916973768cac215 + languageName: node + linkType: hard + "vitest@npm:^3.1.1": version: 3.1.4 resolution: "vitest@npm:3.1.4" @@ -18425,6 +19389,62 @@ __metadata: languageName: node linkType: hard +"vitest@npm:^3.2.2": + version: 3.2.3 + resolution: "vitest@npm:3.2.3" + dependencies: + "@types/chai": "npm:^5.2.2" + "@vitest/expect": "npm:3.2.3" + "@vitest/mocker": "npm:3.2.3" + "@vitest/pretty-format": "npm:^3.2.3" + "@vitest/runner": "npm:3.2.3" + "@vitest/snapshot": "npm:3.2.3" + "@vitest/spy": "npm:3.2.3" + "@vitest/utils": "npm:3.2.3" + chai: "npm:^5.2.0" + debug: "npm:^4.4.1" + expect-type: "npm:^1.2.1" + magic-string: "npm:^0.30.17" + pathe: "npm:^2.0.3" + picomatch: "npm:^4.0.2" + std-env: "npm:^3.9.0" + tinybench: "npm:^2.9.0" + tinyexec: "npm:^0.3.2" + tinyglobby: "npm:^0.2.14" + tinypool: "npm:^1.1.0" + tinyrainbow: "npm:^2.0.0" + vite: "npm:^5.0.0 || ^6.0.0 || ^7.0.0-0" + vite-node: "npm:3.2.3" + why-is-node-running: "npm:^2.3.0" + peerDependencies: + "@edge-runtime/vm": "*" + "@types/debug": ^4.1.12 + "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 + "@vitest/browser": 3.2.3 + "@vitest/ui": 3.2.3 + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@types/debug": + optional: true + "@types/node": + optional: true + "@vitest/browser": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + bin: + vitest: vitest.mjs + checksum: 10c0/1d853016622f32020e91cc72348d0dc642bde2ddcbd648655a9d33d420375c7cbd6f1a6f5c4398a5d4f59b8c2b120e62eba49fb37f8042e5d4c688b7e60148ef + languageName: node + linkType: hard + "vue-template-compiler@npm:^2.7.14": version: 2.7.16 resolution: "vue-template-compiler@npm:2.7.16" @@ -18617,7 +19637,7 @@ __metadata: languageName: node linkType: hard -"why-is-node-running@npm:^2.3.0": +"why-is-node-running@npm:^2.2.2, why-is-node-running@npm:^2.3.0": version: 2.3.0 resolution: "why-is-node-running@npm:2.3.0" dependencies: @@ -18776,7 +19796,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.3.1, yaml@npm:^2.3.4": +"yaml@npm:^2.3.1, yaml@npm:^2.3.4, yaml@npm:^2.5.0": version: 2.8.0 resolution: "yaml@npm:2.8.0" bin: @@ -18821,6 +19841,13 @@ __metadata: languageName: node linkType: hard +"yocto-queue@npm:^1.0.0": + version: 1.2.1 + resolution: "yocto-queue@npm:1.2.1" + checksum: 10c0/5762caa3d0b421f4bdb7a1926b2ae2189fc6e4a14469258f183600028eb16db3e9e0306f46e8ebf5a52ff4b81a881f22637afefbef5399d6ad440824e9b27f9f + languageName: node + linkType: hard + "yoctocolors-cjs@npm:^2.1.2": version: 2.1.2 resolution: "yoctocolors-cjs@npm:2.1.2" @@ -18868,6 +19895,13 @@ __metadata: languageName: node linkType: hard +"zod@npm:^3.25.56": + version: 3.25.56 + resolution: "zod@npm:3.25.56" + checksum: 10c0/3800f01d4b1df932b91354eb1e648f69cc7e5561549e6d2bf83827d930a5f33bbf92926099445f6fc1ebb64ca9c6513ef9ae5e5409cfef6325f354bcf6fc9a24 + languageName: node + linkType: hard + "zustand@npm:^4.3.2": version: 4.5.7 resolution: "zustand@npm:4.5.7" @@ -18895,6 +19929,15 @@ __metadata: languageName: node linkType: hard +"zx@npm:^8.1.9": + version: 8.5.5 + resolution: "zx@npm:8.5.5" + bin: + zx: build/cli.js + checksum: 10c0/9c69e5a75b49b796211812625564980d0a86079a11011b397c4c77d256e3fe0a76b5ec7134db4d598e156f84e07981d8692544715feb8ff77adfae60faa356fc + languageName: node + linkType: hard + "zx@npm:^8.5.0": version: 8.5.4 resolution: "zx@npm:8.5.4"