From 377ce7fb2fc6ab2d0f8a7f305e5b271cca5885d9 Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Fri, 26 Jun 2026 18:01:27 +0530 Subject: [PATCH] feat(cli): support compute app regions --- docs/product/command-spec.md | 17 +- docs/product/resource-model.md | 1 + packages/cli/package.json | 2 +- packages/cli/src/commands/app/index.ts | 8 + packages/cli/src/controllers/app.ts | 296 +++++++++++++------- packages/cli/src/lib/app/compute-config.ts | 78 ++++-- packages/cli/src/lib/app/deploy-plan.ts | 2 + packages/cli/src/shell/command-meta.ts | 1 + packages/cli/tests/app-controller.test.ts | 304 ++++++++++++++++++++- packages/cli/tests/app-env-vars.test.ts | 5 +- packages/cli/tests/app.test.ts | 1 + packages/cli/tests/compute-config.test.ts | 43 +-- packages/cli/tests/deploy-plan.test.ts | 4 + pnpm-lock.yaml | 294 ++++++++++---------- 14 files changed, 769 insertions(+), 287 deletions(-) diff --git a/docs/product/command-spec.md b/docs/product/command-spec.md index 0b82868c..2cd8a5bc 100644 --- a/docs/product/command-spec.md +++ b/docs/product/command-spec.md @@ -58,7 +58,7 @@ Out of scope for the current beta: non-TTY stderr, and when `NO_UPDATE_NOTIFIER` is set. When shown, update notifications are stderr-only human output and do not change the original command result. -- Public Beta does not read or write committed config files such as `prisma.config.ts` or `.prisma/settings.json` for Project -> Branch resolution. `.prisma/local.json` is a gitignored local pin/cache, not a declarative repo config file. `prisma.app.json` is legacy and no longer read or written. `prisma.compute.ts` supplies typed `app deploy` defaults (app name, app root, framework, entrypoint, HTTP port, env inputs) and never selects Project or Branch scope. +- Public Beta does not read or write committed config files such as `prisma.config.ts` or `.prisma/settings.json` for Project -> Branch resolution. `.prisma/local.json` is a gitignored local pin/cache, not a declarative repo config file. `prisma.app.json` is legacy and no longer read or written. `prisma.compute.ts` supplies typed `app deploy` defaults (app name, app region, app root, framework, entrypoint, HTTP port, env inputs) and never selects Project or Branch scope. - Remote commands do not silently change local context. ## Authentication @@ -126,6 +126,9 @@ multiple targets, no argument, and nothing inferred from the invocation directory, they fall back to the selection order above — except step 7; management commands never create apps or mutate remote state to resolve one. +Config `region` and `--region` are not app selectors. They are used only when +`app deploy` creates a new app; existing apps keep their current region. + `.prisma/local.json` pins the directory to a Workspace and Project only. It does not pin an App ID. App services are branch-scoped; a service ID from `main` must not be reused automatically when the user deploys from `feat/billing`. @@ -927,7 +930,7 @@ prisma-cli app run --build-type bun --entry server.ts --port 3000 prisma-cli app run api ``` -## `prisma-cli app deploy [app] --project --create-project --app --branch --framework --entry --http-port --env --db --no-db --prod` +## `prisma-cli app deploy [app] --project --create-project --app --branch --framework --entry --http-port --region --env --db --no-db --prod` Purpose: @@ -943,7 +946,8 @@ Compute config file (`prisma.compute.ts`): - the config defines exactly one of: - `app` — a single-app repository - `apps` — a multi-app or monorepo repository, keyed by deploy target name -- each app accepts `name`, `root`, `framework`, `entry`, `httpPort`, `env`, and `build`: +- each app accepts `name`, `region`, `root`, `framework`, `entry`, `httpPort`, `env`, and `build`: + - `region` is the Compute region id used when deploy creates a new app; existing apps keep their current region - `env` is a dotenv file path, or `{ file, vars }` with file path(s) and inline assignments - `build` is `{ command, outputDirectory, entrypoint }`; all fields are optional except where a framework requires enough information to stage a runnable artifact, and `command: null` skips the build step - `build.entrypoint` is the built artifact entrypoint when `outputDirectory` is set, and is the source entrypoint for Bun/Hono configs that do not set an output directory @@ -959,14 +963,15 @@ with ORM config keys, and `database.schema` will become unnecessary once the unified file's own `schema` field is in scope. Project, branch, and production targeting stay out of committed config in the unified file for the same reasons they are excluded today. -- config values are deploy defaults; explicit flags always win: `--framework`, `--entry`, `--http-port` override per value, and any `--env` flag replaces the config env inputs entirely +- config values are deploy defaults; explicit flags always win: `--framework`, `--entry`, `--http-port`, and `--region` override per value, and any `--env` flag replaces the config env inputs entirely - the config `name` (or the `apps` key when `name` is absent) selects the app like `--app`, but ranks below both `--app` and `PRISMA_APP_ID` +- `--region` and config `region` apply only when the resolved app does not exist yet and deploy creates it; `--app` and `PRISMA_APP_ID` still control which app is selected - `root` is a relative path inside the repository; framework detection, entrypoint resolution, build settings, and the build/upload run in that directory while Project binding and the local pin stay in the config file's directory - `prisma.compute.ts` never selects Project or Branch scope; project resolution is unchanged - the `[app]` argument selects an `apps` target by key: - without an `[app]` argument, a command run from inside a target's `root` selects that target, so `cd apps/api && prisma-cli app deploy` deploys `api`; the deepest matching root wins and an ambiguous tie selects nothing - with multiple `apps` entries, no `[app]` argument, and no target inferred from the invocation directory, deploy deploys every target sequentially in declaration order — the config declares the system, and a bare `prisma-cli app deploy` ships it - - deploying all targets rejects per-app inputs (`--app`, `--framework`, `--entry`, `--http-port`, `--env`, `PRISMA_APP_ID`) with a usage error; project- and branch-level flags (`--project`, `--create-project`, `--branch`, `--db`, `--no-db`, `--prod`, `--yes`) apply to the whole run, with `--create-project` creating and binding the Project once before the first target + - deploying all targets rejects per-app inputs (`--app`, `--framework`, `--entry`, `--http-port`, `--region`, `--env`, `PRISMA_APP_ID`) with a usage error; project- and branch-level flags (`--project`, `--create-project`, `--branch`, `--db`, `--no-db`, `--prod`, `--yes`) apply to the whole run, with `--create-project` creating and binding the Project once before the first target - a deploy-all run stops at the first failure and reports the targets already live; `--json` output aggregates one full deploy result per target - `app build` and `app run` still require a target in multi-app configs and fail with `COMPUTE_CONFIG_TARGET_REQUIRED` (a dev server cannot run N apps at once; build keeps the same shape) - an `[app]` argument that matches no target fails with `COMPUTE_CONFIG_TARGET_UNKNOWN` @@ -983,6 +988,7 @@ import { defineComputeConfig } from "@prisma/compute-sdk/config"; export default defineComputeConfig({ app: { name: "api", + region: "eu-central-1", framework: "hono", httpPort: 8080, env: ".env", @@ -1079,6 +1085,7 @@ prisma-cli app deploy prisma-cli app deploy --project proj_123 prisma-cli app deploy --create-project my-app --yes prisma-cli app deploy --app my-app --env DATABASE_URL=postgresql://example +prisma-cli app deploy --app my-app --region us-west-1 prisma-cli app deploy --db prisma-cli app deploy --db --yes prisma-cli app deploy --no-db diff --git a/docs/product/resource-model.md b/docs/product/resource-model.md index 60a32f83..ae19cb82 100644 --- a/docs/product/resource-model.md +++ b/docs/product/resource-model.md @@ -104,6 +104,7 @@ Rules: - the runtime app service is scoped by branch in the platform model - the app may be selected or created as part of app deployment workflows - app selection is local CLI state when needed for the beta package +- app region is set at app creation time; `prisma.compute.ts` can provide the new-app default, but deploys to existing apps do not move them between regions - app build settings live in the `build` block of `prisma.compute.ts` (`command`, `outputDirectory`, `entrypoint`); `prisma.app.json` is legacy and no longer read ### Deployment diff --git a/packages/cli/package.json b/packages/cli/package.json index f291935f..adb5d400 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -44,7 +44,7 @@ }, "dependencies": { "@clack/prompts": "^1.5.0", - "@prisma/compute-sdk": "0.30.0", + "@prisma/compute-sdk": "0.31.0", "@prisma/credentials-store": "^7.8.0", "@prisma/management-api-sdk": "^1.44.0", "better-result": "^2.9.2", diff --git a/packages/cli/src/commands/app/index.ts b/packages/cli/src/commands/app/index.ts index 7bbe7ebd..7c1e20fd 100644 --- a/packages/cli/src/commands/app/index.ts +++ b/packages/cli/src/commands/app/index.ts @@ -228,6 +228,12 @@ function createDeployCommand(runtime: CliRuntime): Command { "HTTP port override for the deployed app", ), ) + .addOption( + new Option( + "--region ", + "Region for a newly created app; existing apps keep their region", + ), + ) .addOption( new Option( "--env ", @@ -250,6 +256,7 @@ function createDeployCommand(runtime: CliRuntime): Command { const branchName = (options as { branch?: string }).branch; const framework = (options as { framework?: string }).framework; const httpPort = (options as { httpPort?: string }).httpPort; + const region = (options as { region?: string }).region; const envAssignments = (options as { env?: string[] }).env; const projectRef = (options as { project?: string }).project; const createProjectName = (options as { createProject?: string }) @@ -281,6 +288,7 @@ function createDeployCommand(runtime: CliRuntime): Command { entrypoint: entry, framework, httpPort, + region, envAssignments, prod: prod === true, db, diff --git a/packages/cli/src/controllers/app.ts b/packages/cli/src/controllers/app.ts index 669193f6..442cc015 100644 --- a/packages/cli/src/controllers/app.ts +++ b/packages/cli/src/controllers/app.ts @@ -2,6 +2,7 @@ import { access, readFile } from "node:fs/promises"; import path from "node:path"; import type { PortMapping, StreamRecord } from "@prisma/compute-sdk"; import { + COMPUTE_REGIONS, type ComputeFramework, type ConfigBackedBuildType, ENTRYPOINT_BUILD_TYPES, @@ -38,7 +39,6 @@ import { executeAppBuild, PRISMA_APP_CONFIG_FILENAME, RESOLVED_APP_BUILD_TYPES, - type ResolvedAppBuildType, resolveConfiguredAppBuildSettings, resolveInferredAppBuildSettings, } from "../lib/app/build"; @@ -165,6 +165,7 @@ type AppDomainCommand = "add" | "show" | "remove" | "retry" | "wait"; const FRAMEWORK_DEFAULT_HTTP_PORT = 3000; const PRISMA_PROJECT_ID_ENV_VAR = "PRISMA_PROJECT_ID"; const PRISMA_APP_ID_ENV_VAR = "PRISMA_APP_ID"; +const COMPUTE_REGION_IDS = new Set(COMPUTE_REGIONS); function isRealMode(context: CommandContext): boolean { return ( @@ -373,6 +374,7 @@ interface AppDeployOptions { entrypoint?: string; framework?: string; httpPort?: string; + region?: string; envAssignments?: string[]; prod?: boolean; db?: boolean; @@ -427,7 +429,7 @@ async function runAppDeployAll( appName: string | undefined, options?: AppDeployOptions, ): Promise> { - assertNoPerAppInputsForDeployAll(context, config, appName, options); + assertNoPerAppInputsForDeployAll(context, plannedTargets, appName, options); const deployments: AppDeployAllResult["deployments"] = []; const warnings: string[] = []; @@ -444,6 +446,7 @@ async function runAppDeployAll( : undefined, }; try { + // biome-ignore lint/performance/noAwaitInLoops: deploy-all must run in order so --create-project writes the local project pin before later targets resolve it. const single = await runSingleAppDeploy( context, undefined, @@ -453,7 +456,12 @@ async function runAppDeployAll( deployments.push({ target: planned.targetKey, result: single.result }); warnings.push(...single.warnings); } catch (error) { - throw deployAllFailedError(error, config, planned.index, deployments); + throw deployAllFailedError( + error, + plannedTargets, + planned.index, + deployments, + ); } } @@ -469,7 +477,7 @@ async function runAppDeployAll( function assertNoPerAppInputsForDeployAll( context: CommandContext, - config: LoadedComputeConfig, + plannedTargets: PlannedDeployTarget[], appName: string | undefined, options?: AppDeployOptions, ): void { @@ -478,6 +486,7 @@ function assertNoPerAppInputsForDeployAll( framework: options?.framework, entrypoint: options?.entrypoint, httpPort: options?.httpPort, + region: options?.region, envAssignments: options?.envAssignments, appIdEnvVar: { name: PRISMA_APP_ID_ENV_VAR, @@ -488,12 +497,12 @@ function assertNoPerAppInputsForDeployAll( return; } - const targets = config.targets.map((target) => target.key!).join(", "); + const targetKeys = plannedTargets.map((target) => target.targetKey); throw usageError( `Deploying all apps does not accept ${used.join(", ")}`, - `Without a target, app deploy deploys every configured app (${targets}), so per-app inputs are ambiguous.`, + `Without a target, app deploy deploys every configured app (${targetKeys.join(", ")}), so per-app inputs are ambiguous.`, "Pass the app target to apply per-app inputs to one app, or remove them to deploy all apps.", - config.targets.map((target) => `prisma-cli app deploy ${target.key}`), + targetKeys.map((target) => `prisma-cli app deploy ${target}`), "app", ); } @@ -513,7 +522,7 @@ function maybeRenderDeployAllTargetHeader( function deployAllFailedError( error: unknown, - config: LoadedComputeConfig, + plannedTargets: PlannedDeployTarget[], failedIndex: number, deployments: AppDeployAllResult["deployments"], ): unknown { @@ -522,7 +531,7 @@ function deployAllFailedError( } const failure = describeDeployAllFailure({ - targetKeys: config.targets.map((target) => target.key!), + targetKeys: plannedTargets.map((target) => target.targetKey), failedIndex, completed: deployments.map(({ target, result }) => ({ target, @@ -593,6 +602,7 @@ async function runSingleAppDeploy( framework: options?.framework, entrypoint: options?.entrypoint, httpPort: options?.httpPort, + region: options?.region, envInputs: options?.envAssignments, }, target: computeConfig.target, @@ -619,6 +629,7 @@ async function runSingleAppDeploy( if (merged.httpPort) { parseDeployHttpPort(merged.httpPort.value); } + const deployRegion = normalizeDeployRegionInput(merged.region); assertSupportedEntrypointForRequestedDeployShape({ requestedFramework: merged.framework?.value, entrypoint: merged.entrypoint?.value, @@ -689,6 +700,7 @@ async function runSingleAppDeploy( explicitAppName: appName, explicitAppId: envAppId, configAppName: merged.configAppName, + configRegion: deployRegion, firstDeploy: Boolean(target.localPinAction), inferName: () => inferTargetName(appDir, context.runtime.signal), }, @@ -734,27 +746,12 @@ async function runSingleAppDeploy( merged.entrypoint?.value, context.runtime.signal, ); - if (computeConfig.target?.build) { - assertConfigBackedBuildSettings(buildType); - } - // Build settings come from the compute config's build block over framework - // defaults; nothing is read from or written to disk for them. - const buildSettingsResolution = - computeConfig.config && - computeConfig.target?.build && - isConfigBackedBuildType(buildType) - ? await resolveConfiguredAppBuildSettings({ - appPath: appDir, - buildType, - configured: computeConfig.target.build, - configPath: computeConfig.config.configPath, - signal: context.runtime.signal, - }) - : await resolveInferredAppBuildSettings({ - appPath: appDir, - buildType, - signal: context.runtime.signal, - }); + const buildSettingsResolution = await resolveDeployBuildSettings({ + computeConfig, + appDir, + buildType, + signal: context.runtime.signal, + }); const legacyWarnings = await handleLegacyBuildSettings( context, appDir, @@ -849,7 +846,7 @@ async function runSingleAppDeploy( entrypoint: entrypoint ?? buildSettingsResolution.settings.entrypoint ?? null, httpPort: runtime.port, - region: selectedApp.region ?? null, + region: deployResult.app.region ?? selectedApp.region ?? null, envVars: envVarNames(envVars), }, durationMs: deployDurationMs, @@ -863,6 +860,44 @@ async function runSingleAppDeploy( }; } +async function resolveDeployBuildSettings(options: { + computeConfig: { + config: LoadedComputeConfig | null; + target: ComputeDeployTarget | null; + }; + appDir: string; + buildType: FrameworkBuildType; + signal: AbortSignal; +}): Promise { + const { computeConfig, appDir, buildType, signal } = options; + + if (computeConfig.target?.build) { + assertConfigBackedBuildSettings(buildType); + } + + // Build settings come from the compute config's build block over framework + // defaults; nothing is read from or written to disk for them. + if ( + computeConfig.config && + computeConfig.target?.build && + isConfigBackedBuildType(buildType) + ) { + return resolveConfiguredAppBuildSettings({ + appPath: appDir, + buildType, + configured: computeConfig.target.build, + configPath: computeConfig.config.configPath, + signal, + }); + } + + return resolveInferredAppBuildSettings({ + appPath: appDir, + buildType, + signal, + }); +} + export async function runAppListDeploys( context: CommandContext, appName: string | undefined, @@ -2623,6 +2658,7 @@ async function resolveDeployAppSelection( explicitAppName: string | undefined; explicitAppId: string | undefined; configAppName: MergedDeployInput | undefined; + configRegion: MergedDeployInput | undefined; firstDeploy: boolean; inferName: () => Promise; }, @@ -2634,33 +2670,16 @@ async function resolveDeployAppSelection( annotation: string; firstDeploy: boolean; }> { + const newAppRegion = deployNewAppRegion(options.configRegion); if (options.explicitAppName) { - const matches = findAppsByName(apps, options.explicitAppName); - if (matches.length > 1) { - return resolveAmbiguousDeployApp( - context, - matches, - options.explicitAppName, - options.firstDeploy, - ); - } - const matched = matches[0]; - if (matched) { - return { - appId: matched.id, - displayName: matched.name, - annotation: "set by --app", - firstDeploy: options.firstDeploy, - }; - } - - return { - appName: options.explicitAppName, - region: DEFAULT_REGION, - displayName: options.explicitAppName, - annotation: "set by --app", + return resolveDeployAppByName(context, apps, { + name: options.explicitAppName, + matchedAnnotation: "set by --app", + newAnnotation: "set by --app", + requestedRegion: options.configRegion, + newAppRegion, firstDeploy: options.firstDeploy, - }; + }); } if (options.explicitAppId) { @@ -2674,6 +2693,7 @@ async function resolveDeployAppSelection( "app", ); } + assertDeployRegionMatchesExistingApp(matched, options.configRegion); return { appId: matched.id, @@ -2685,72 +2705,112 @@ async function resolveDeployAppSelection( if (options.configAppName) { const configName = options.configAppName; - const matches = findAppsByName(apps, configName.value); - if (matches.length > 1) { - return resolveAmbiguousDeployApp( - context, - matches, - configName.value, - options.firstDeploy, - ); - } - - const matched = matches[0]; - if (matched) { - return { - appId: matched.id, - displayName: matched.name, - annotation: configName.annotation, - firstDeploy: options.firstDeploy, - }; - } - - return { - appName: configName.value, - region: DEFAULT_REGION, - displayName: configName.value, - annotation: configName.annotation, + return resolveDeployAppByName(context, apps, { + name: configName.value, + matchedAnnotation: configName.annotation, + newAnnotation: configName.annotation, + requestedRegion: options.configRegion, + newAppRegion, firstDeploy: options.firstDeploy, - }; + }); } const inferredName = await options.inferName(); - const matches = findAppsByName(apps, inferredName.name); + const newAnnotation = + inferredName.source === "package-name" + ? "created from package.json" + : "created from directory name"; + return resolveDeployAppByName(context, apps, { + name: inferredName.name, + matchedAnnotation: "existing app on this branch", + newAnnotation, + requestedRegion: options.configRegion, + newAppRegion, + firstDeploy: options.firstDeploy, + }); +} + +async function resolveDeployAppByName( + context: CommandContext, + apps: AppRecord[], + options: { + name: string; + matchedAnnotation: string; + newAnnotation: string; + requestedRegion: MergedDeployInput | undefined; + newAppRegion: string; + firstDeploy: boolean; + }, +): Promise<{ + appId?: string; + appName?: string; + region?: string; + displayName: string; + annotation: string; + firstDeploy: boolean; +}> { + const matches = findAppsByName(apps, options.name); if (matches.length > 1) { return resolveAmbiguousDeployApp( context, matches, - inferredName.name, + options.name, + options.requestedRegion, + options.newAppRegion, options.firstDeploy, ); } const matched = matches[0]; if (matched) { + assertDeployRegionMatchesExistingApp(matched, options.requestedRegion); return { appId: matched.id, displayName: matched.name, - annotation: "existing app on this branch", + annotation: options.matchedAnnotation, firstDeploy: options.firstDeploy, }; } return { - appName: inferredName.name, - region: DEFAULT_REGION, - displayName: inferredName.name, - annotation: - inferredName.source === "package-name" - ? "created from package.json" - : "created from directory name", + appName: options.name, + region: options.newAppRegion, + displayName: options.name, + annotation: options.newAnnotation, firstDeploy: options.firstDeploy, }; } +function assertDeployRegionMatchesExistingApp( + app: AppRecord, + requestedRegion: MergedDeployInput | undefined, +): void { + if ( + requestedRegion?.annotation !== "set by --region" || + !app.region || + app.region === requestedRegion.value + ) { + return; + } + + throw usageError( + "App already exists in another region", + `The selected app "${app.name}" is in region "${app.region}", but --region requested "${requestedRegion.value}".`, + "Remove --region to deploy the existing app, or pass --app to create a new app in that region.", + [ + `prisma-cli app deploy --app ${formatCommandArgument(app.name)}`, + `prisma-cli app deploy --app --region ${formatCommandArgument(requestedRegion.value)}`, + ], + "app", + ); +} + async function resolveAmbiguousDeployApp( context: CommandContext, matches: AppRecord[], targetName: string, + requestedRegion: MergedDeployInput | undefined, + newAppRegion: string, firstDeploy: boolean, ): Promise<{ appId?: string; @@ -2798,13 +2858,15 @@ async function resolveAmbiguousDeployApp( if (selected === createNew) { return { appName: targetName, - region: DEFAULT_REGION, + region: newAppRegion, displayName: targetName, annotation: "created from package.json", firstDeploy, }; } + assertDeployRegionMatchesExistingApp(selected, requestedRegion); + return { appId: selected.id, displayName: selected.name, @@ -2827,6 +2889,12 @@ async function resolveAmbiguousDeployApp( }); } +function deployNewAppRegion( + configRegion: MergedDeployInput | undefined, +): string { + return configRegion?.value ?? DEFAULT_REGION; +} + async function resolveExistingAppSelection( context: CommandContext, projectId: string, @@ -4339,10 +4407,6 @@ function maybeRenderDeploySettingsPreview( ); } -function frameworkDisplayName(framework: ComputeFramework): string { - return frameworkByKey(framework).displayName; -} - function validateDeployHttpPortText( value: string | undefined, ): string | undefined { @@ -4560,6 +4624,44 @@ function parseDeployHttpPort(requestedPort: string): number { return port; } +function parseDeployRegion(requestedRegion: string, source: string): string { + const region = requestedRegion.trim(); + if (region.length === 0) { + throw usageError( + "Invalid app region", + `The app region ${source} must be a non-empty region id.`, + "Pass a Prisma Compute region id.", + ["prisma-cli app deploy --region eu-central-1"], + "app", + ); + } + + if (!COMPUTE_REGION_IDS.has(region)) { + throw usageError( + "Invalid app region", + `The app region ${source} must be one of: ${COMPUTE_REGIONS.join(", ")}.`, + "Pass a supported Prisma Compute region id.", + ["prisma-cli app deploy --region eu-central-1"], + "app", + ); + } + + return region; +} + +function normalizeDeployRegionInput( + region: MergedDeployInput | undefined, +): MergedDeployInput | undefined { + if (!region) { + return undefined; + } + + return { + ...region, + value: parseDeployRegion(region.value, region.annotation), + }; +} + function ensurePreviewAppMode(context: CommandContext) { if (isRealMode(context)) { return; diff --git a/packages/cli/src/lib/app/compute-config.ts b/packages/cli/src/lib/app/compute-config.ts index cb073b26..b33f5bf9 100644 --- a/packages/cli/src/lib/app/compute-config.ts +++ b/packages/cli/src/lib/app/compute-config.ts @@ -67,6 +67,8 @@ export interface MergedComputeDeployInputs { framework: MergedDeployInput | undefined; entrypoint: MergedDeployInput | undefined; httpPort: MergedDeployInput | undefined; + /** Region from config, applied only when the deploy creates a new app. */ + region: MergedDeployInput | undefined; /** `--env` flags replace config env inputs entirely; they never merge. */ envInputs: string[] | undefined; /** True when env inputs came from the config; their file paths then resolve from the config directory. */ @@ -82,6 +84,7 @@ export function mergeComputeDeployInputs(options: { framework?: string; entrypoint?: string; httpPort?: string; + region?: string; envInputs?: string[]; }; target: ComputeDeployTarget | null; @@ -90,23 +93,31 @@ export function mergeComputeDeployInputs(options: { const { cli, target, configFilename } = options; const configAnnotation = `set by ${configFilename}`; - const framework = cli.framework - ? { value: cli.framework, annotation: "set by --framework" } - : target?.framework - ? { value: target.framework, annotation: configAnnotation } - : undefined; + const framework = mergeStringInput( + cli.framework, + "set by --framework", + target?.framework ?? undefined, + configAnnotation, + ); + const entrypoint = mergeStringInput( + cli.entrypoint, + "set by --entry", + target?.entry ?? undefined, + configAnnotation, + ); + const httpPort = mergeStringInput( + cli.httpPort, + "set by --http-port", + target?.httpPort ? String(target.httpPort) : undefined, + configAnnotation, + ); - const entrypoint = cli.entrypoint - ? { value: cli.entrypoint, annotation: "set by --entry" } - : target?.entry - ? { value: target.entry, annotation: configAnnotation } - : undefined; - - const httpPort = cli.httpPort - ? { value: cli.httpPort, annotation: "set by --http-port" } - : target?.httpPort - ? { value: String(target.httpPort), annotation: configAnnotation } - : undefined; + const region = mergeStringInput( + cli.region, + "set by --region", + target?.region ?? undefined, + configAnnotation, + ); const cliEnvInputs = cli.envInputs && cli.envInputs.length > 0 ? cli.envInputs : undefined; @@ -114,16 +125,13 @@ export function mergeComputeDeployInputs(options: { target && target.envInputs.length > 0 ? target.envInputs : undefined; const envInputs = cliEnvInputs ?? configEnvInputs; - const configAppName = target?.name - ? { value: target.name, annotation: configAnnotation } - : target?.key - ? { value: target.key, annotation: configAnnotation } - : undefined; + const configAppName = readConfigAppName(target, configAnnotation); return { framework, entrypoint, httpPort, + region, envInputs, envInputsFromConfig: !cliEnvInputs && configEnvInputs !== undefined, configAppName, @@ -131,6 +139,34 @@ export function mergeComputeDeployInputs(options: { }; } +function mergeStringInput( + cliValue: string | undefined, + cliAnnotation: string, + configValue: string | undefined, + configAnnotation: string, +): MergedDeployInput | undefined { + if (cliValue !== undefined) { + return { value: cliValue, annotation: cliAnnotation }; + } + if (configValue) { + return { value: configValue, annotation: configAnnotation }; + } + return undefined; +} + +function readConfigAppName( + target: ComputeDeployTarget | null, + configAnnotation: string, +): MergedDeployInput | undefined { + if (target?.name) { + return { value: target.name, annotation: configAnnotation }; + } + if (target?.key) { + return { value: target.key, annotation: configAnnotation }; + } + return undefined; +} + export interface MergedComputeLocalInputs { entrypoint: string | undefined; /** Resolved build type, or undefined for auto detection. */ diff --git a/packages/cli/src/lib/app/deploy-plan.ts b/packages/cli/src/lib/app/deploy-plan.ts index 5198ec0d..2f51815f 100644 --- a/packages/cli/src/lib/app/deploy-plan.ts +++ b/packages/cli/src/lib/app/deploy-plan.ts @@ -67,6 +67,7 @@ export interface DeployAllPerAppInputs { framework: string | undefined; entrypoint: string | undefined; httpPort: string | undefined; + region: string | undefined; envAssignments: string[] | undefined; /** App-id environment override, passed with its variable name for the message. */ appIdEnvVar: { name: string; value: string | undefined }; @@ -85,6 +86,7 @@ export function perAppInputsForDeployAll( ["--framework", inputs.framework], ["--entry", inputs.entrypoint], ["--http-port", inputs.httpPort], + ["--region", inputs.region], [ "--env", inputs.envAssignments?.length ? inputs.envAssignments : undefined, diff --git a/packages/cli/src/shell/command-meta.ts b/packages/cli/src/shell/command-meta.ts index 0b869a57..f41878b4 100644 --- a/packages/cli/src/shell/command-meta.ts +++ b/packages/cli/src/shell/command-meta.ts @@ -293,6 +293,7 @@ const DESCRIPTORS: CommandDescriptor[] = [ "prisma-cli app deploy --db", "prisma-cli app deploy --db --yes", "prisma-cli app deploy --app my-app --framework nextjs --http-port 3000", + "prisma-cli app deploy --app my-app --region us-west-1", "prisma-cli app deploy --branch feat-login --framework hono", "prisma-cli app deploy --prod --yes", "prisma-cli app deploy --framework bun --entry src/server.ts", diff --git a/packages/cli/tests/app-controller.test.ts b/packages/cli/tests/app-controller.test.ts index 5dcbb750..6baef557 100644 --- a/packages/cli/tests/app-controller.test.ts +++ b/packages/cli/tests/app-controller.test.ts @@ -1,6 +1,8 @@ -import { mkdir, readFile, writeFile } from "node:fs/promises"; +import { mkdir, mkdtemp, readFile, writeFile } from "node:fs/promises"; +import os from "node:os"; import path from "node:path"; +import { Result } from "better-result"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { asSingleDeployResult } from "./helpers/deploy-result"; @@ -40,6 +42,7 @@ afterEach(() => { vi.doUnmock("../src/lib/auth/guard"); vi.doUnmock("../src/lib/app/app-provider"); vi.doUnmock("../src/lib/app/branch-database"); + vi.doUnmock("../src/lib/app/compute-config"); vi.doUnmock("../src/shell/prompt"); vi.doUnmock("open"); vi.resetModules(); @@ -264,6 +267,301 @@ describe("app controller", () => { }); }); + it("uses the configured region when creating a new app from config", async () => { + const cwd = await mkdtemp(path.join(os.tmpdir(), "prisma-cli-")); + const requireComputeAuth = vi.fn().mockResolvedValue(createProjectClient()); + const listApps = vi.fn().mockResolvedValue([]); + const deployApp = vi.fn().mockResolvedValue({ + projectId: "proj_123", + app: { + id: "app_new", + name: "frontend", + region: "us-west-1", + liveDeploymentId: "dep_123", + }, + deployment: { + id: "dep_123", + status: "running", + url: "https://frontend.prisma.app", + }, + }); + + vi.doMock("../src/lib/auth/guard", () => ({ + requireComputeAuth, + })); + vi.doMock("../src/lib/app/app-provider", () => ({ + createAppProvider: vi.fn(() => + withBranchDatabaseProviderDefaults({ + resolveBranch: createResolveBranch(), + listApps, + deployApp, + listDeployments: vi.fn(), + showDeployment: vi.fn(), + }), + ), + })); + vi.doMock("../src/lib/app/compute-config", async (importOriginal) => { + const actual = + await importOriginal(); + return { + ...actual, + loadComputeConfig: vi.fn().mockResolvedValue( + Result.ok({ + configPath: path.join(cwd, "prisma.compute.ts"), + configDir: cwd, + relativeConfigPath: "prisma.compute.ts", + kind: "single", + targets: [ + { + key: null, + name: "frontend", + region: "us-west-1", + root: null, + framework: "hono", + entry: null, + httpPort: null, + envInputs: [], + build: null, + }, + ], + }), + ), + }; + }); + + const { createTestCommandContext } = await import("./helpers"); + const { runAppDeploy } = await import("../src/controllers/app"); + const { context } = await createTestCommandContext({ + cwd, + stateDir: path.join(cwd, ".state"), + isTTY: false, + env: { + ...process.env, + PRISMA_CLI_MOCK_FIXTURE_PATH: undefined, + }, + }); + + const result = await runAppDeploy(context, undefined, { + projectRef: "proj_123", + }); + + expect(deployApp).toHaveBeenCalledWith( + expect.objectContaining({ + appName: "frontend", + region: "us-west-1", + }), + ); + expect(asSingleDeployResult(result).result.deploySettings.region).toBe( + "us-west-1", + ); + }); + + it("uses --region when creating a new app", async () => { + const requireComputeAuth = vi.fn().mockResolvedValue(createProjectClient()); + const listApps = vi.fn().mockResolvedValue([]); + const deployApp = vi.fn().mockResolvedValue({ + projectId: "proj_123", + app: { + id: "app_new", + name: "frontend", + region: "ap-southeast-1", + liveDeploymentId: "dep_123", + }, + deployment: { + id: "dep_123", + status: "running", + url: "https://frontend.prisma.app", + }, + }); + + vi.doMock("../src/lib/auth/guard", () => ({ + requireComputeAuth, + })); + vi.doMock("../src/lib/app/app-provider", () => ({ + createAppProvider: vi.fn(() => + withBranchDatabaseProviderDefaults({ + resolveBranch: createResolveBranch(), + listApps, + deployApp, + listDeployments: vi.fn(), + showDeployment: vi.fn(), + }), + ), + })); + + const { createTempCwd, createTestCommandContext } = await import( + "./helpers" + ); + const { runAppDeploy } = await import("../src/controllers/app"); + const cwd = await createTempCwd(); + const { context } = await createTestCommandContext({ + cwd, + stateDir: path.join(cwd, ".state"), + isTTY: false, + env: { + ...process.env, + PRISMA_CLI_MOCK_FIXTURE_PATH: undefined, + }, + }); + + const result = await runAppDeploy(context, "frontend", { + projectRef: "proj_123", + framework: "hono", + region: "ap-southeast-1", + }); + + expect(deployApp).toHaveBeenCalledWith( + expect.objectContaining({ + appName: "frontend", + region: "ap-southeast-1", + }), + ); + expect(asSingleDeployResult(result).result.deploySettings.region).toBe( + "ap-southeast-1", + ); + }); + + it("rejects unsupported --region values before deploy", async () => { + const { createTempCwd, createTestCommandContext } = await import( + "./helpers" + ); + const { runAppDeploy } = await import("../src/controllers/app"); + const cwd = await createTempCwd(); + const { context } = await createTestCommandContext({ + cwd, + stateDir: path.join(cwd, ".state"), + isTTY: false, + env: { + ...process.env, + PRISMA_CLI_MOCK_FIXTURE_PATH: undefined, + }, + }); + + await expect( + runAppDeploy(context, "frontend", { + projectRef: "proj_123", + framework: "hono", + region: "moon-1", + }), + ).rejects.toMatchObject({ + code: "USAGE_ERROR", + summary: "Invalid app region", + }); + }); + + it("rejects --region when the selected app already exists in another region", async () => { + const requireComputeAuth = vi.fn().mockResolvedValue(createProjectClient()); + const listApps = vi.fn().mockResolvedValue([ + { + id: "app_frontend", + name: "frontend", + region: "eu-west-3", + liveDeploymentId: "dep_live", + liveUrl: null, + }, + ]); + const deployApp = vi.fn(); + + vi.doMock("../src/lib/auth/guard", () => ({ + requireComputeAuth, + })); + vi.doMock("../src/lib/app/app-provider", () => ({ + createAppProvider: vi.fn(() => + withBranchDatabaseProviderDefaults({ + resolveBranch: createResolveBranch(), + listApps, + deployApp, + listDeployments: vi.fn(), + showDeployment: vi.fn(), + }), + ), + })); + + const { createTempCwd, createTestCommandContext } = await import( + "./helpers" + ); + const { runAppDeploy } = await import("../src/controllers/app"); + const cwd = await createTempCwd(); + const { context } = await createTestCommandContext({ + cwd, + stateDir: path.join(cwd, ".state"), + isTTY: false, + env: { + ...process.env, + PRISMA_CLI_MOCK_FIXTURE_PATH: undefined, + }, + }); + + await expect( + runAppDeploy(context, "frontend", { + projectRef: "proj_123", + framework: "hono", + region: "us-west-1", + }), + ).rejects.toMatchObject({ + code: "USAGE_ERROR", + summary: "App already exists in another region", + }); + expect(deployApp).not.toHaveBeenCalled(); + }); + + it("rejects --region when PRISMA_APP_ID selects an app in another region", async () => { + const requireComputeAuth = vi.fn().mockResolvedValue(createProjectClient()); + const listApps = vi.fn().mockResolvedValue([ + { + id: "app_frontend", + name: "frontend", + region: "eu-west-3", + liveDeploymentId: "dep_live", + liveUrl: null, + }, + ]); + const deployApp = vi.fn(); + + vi.doMock("../src/lib/auth/guard", () => ({ + requireComputeAuth, + })); + vi.doMock("../src/lib/app/app-provider", () => ({ + createAppProvider: vi.fn(() => + withBranchDatabaseProviderDefaults({ + resolveBranch: createResolveBranch(), + listApps, + deployApp, + listDeployments: vi.fn(), + showDeployment: vi.fn(), + }), + ), + })); + + const { createTempCwd, createTestCommandContext } = await import( + "./helpers" + ); + const { runAppDeploy } = await import("../src/controllers/app"); + const cwd = await createTempCwd(); + const { context } = await createTestCommandContext({ + cwd, + stateDir: path.join(cwd, ".state"), + isTTY: false, + env: { + ...process.env, + PRISMA_APP_ID: "app_frontend", + PRISMA_CLI_MOCK_FIXTURE_PATH: undefined, + }, + }); + + await expect( + runAppDeploy(context, undefined, { + projectRef: "proj_123", + framework: "hono", + region: "us-west-1", + }), + ).rejects.toMatchObject({ + code: "USAGE_ERROR", + summary: "App already exists in another region", + }); + expect(deployApp).not.toHaveBeenCalled(); + }); + it("deploy-all stops at the first failing target and reports the rest", async () => { const requireComputeAuth = vi.fn().mockResolvedValue(createProjectClient()); const listApps = vi.fn().mockResolvedValue([]); @@ -358,10 +656,10 @@ describe("app controller", () => { }); await expect( - runAppDeploy(context, undefined, { framework: "hono" }), + runAppDeploy(context, undefined, { region: "us-west-1" }), ).rejects.toMatchObject({ code: "USAGE_ERROR", - summary: expect.stringContaining("--framework"), + summary: expect.stringContaining("--region"), }); }); diff --git a/packages/cli/tests/app-env-vars.test.ts b/packages/cli/tests/app-env-vars.test.ts index a4fe3176..ee7e72ad 100644 --- a/packages/cli/tests/app-env-vars.test.ts +++ b/packages/cli/tests/app-env-vars.test.ts @@ -556,7 +556,7 @@ describe("app env vars", () => { expect(JSON.stringify(result.result)).not.toContain("enabled"); }); - it("parses deploy build, port, prod, explicit project, and JSON output through the CLI command layer", async () => { + it("parses deploy build, port, region, prod, explicit project, and JSON output through the CLI command layer", async () => { const runAppDeploy = vi.fn().mockResolvedValue({ command: "app.deploy", result: { @@ -637,6 +637,8 @@ describe("app env vars", () => { "nextjs", "--http-port", "3000", + "--region", + "us-west-1", "--env", "DATABASE_URL=postgresql://example", "--project", @@ -699,6 +701,7 @@ describe("app env vars", () => { entrypoint: undefined, framework: "nextjs", httpPort: "3000", + region: "us-west-1", envAssignments: ["DATABASE_URL=postgresql://example"], projectRef: "proj_123", prod: true, diff --git a/packages/cli/tests/app.test.ts b/packages/cli/tests/app.test.ts index 396a1c84..39390928 100644 --- a/packages/cli/tests/app.test.ts +++ b/packages/cli/tests/app.test.ts @@ -174,6 +174,7 @@ describe("app commands", () => { expect(deployHelp.stderr).toContain("--framework "); expect(deployHelp.stderr).not.toContain("--build-type "); expect(deployHelp.stderr).toContain("--http-port "); + expect(deployHelp.stderr).toContain("--region "); expect(deployHelp.stderr).toContain("--env "); expect(deployHelp.stderr).toContain("--db"); expect(deployHelp.stderr).toContain("--no-db"); diff --git a/packages/cli/tests/compute-config.test.ts b/packages/cli/tests/compute-config.test.ts index 22a7920d..d702ed55 100644 --- a/packages/cli/tests/compute-config.test.ts +++ b/packages/cli/tests/compute-config.test.ts @@ -58,18 +58,17 @@ describe("normalizeComputeConfig", () => { expect(config.kind).toBe("single"); expect(config.relativeConfigPath).toBe(COMPUTE_CONFIG_FILENAME); - expect(config.targets).toEqual([ - { - key: null, - name: "api", - root: null, - framework: "hono", - entry: null, - httpPort: 8080, - envInputs: [".env"], - build: null, - }, - ]); + expect(config.targets).toHaveLength(1); + expect(config.targets[0]).toMatchObject({ + key: null, + name: "api", + root: null, + framework: "hono", + entry: null, + httpPort: 8080, + envInputs: [".env"], + build: null, + }); }); it("normalizes a multi-app config with roots and env objects", () => { @@ -351,16 +350,17 @@ describe("selectComputeDeployTarget", () => { }); describe("mergeComputeDeployInputs", () => { - const target: ComputeDeployTarget = { + const target = { key: "web", name: null, + region: "us-west-1", root: "apps/web", framework: "nextjs", entry: null, httpPort: 8080, envInputs: [".env", "LOG_LEVEL=debug"], build: null, - }; + } as ComputeDeployTarget; it("uses config values when flags are absent", () => { const merged = mergeComputeDeployInputs({ @@ -377,6 +377,10 @@ describe("mergeComputeDeployInputs", () => { value: "8080", annotation: "set by prisma.compute.ts", }); + expect(merged.region).toEqual({ + value: "us-west-1", + annotation: "set by prisma.compute.ts", + }); expect(merged.envInputs).toEqual([".env", "LOG_LEVEL=debug"]); expect(merged.configAppName).toEqual({ value: "web", @@ -391,6 +395,7 @@ describe("mergeComputeDeployInputs", () => { framework: "bun", entrypoint: "server.ts", httpPort: "3000", + region: "eu-west-3", envInputs: ["DATABASE_URL=postgresql://example"], }, target, @@ -409,6 +414,10 @@ describe("mergeComputeDeployInputs", () => { value: "3000", annotation: "set by --http-port", }); + expect(merged.region).toEqual({ + value: "eu-west-3", + annotation: "set by --region", + }); // --env replaces config env inputs entirely; they never merge. expect(merged.envInputs).toEqual(["DATABASE_URL=postgresql://example"]); }); @@ -435,6 +444,7 @@ describe("mergeComputeDeployInputs", () => { annotation: "set by --framework", }); expect(merged.entrypoint).toBeUndefined(); + expect(merged.region).toBeUndefined(); expect(merged.envInputs).toBeUndefined(); expect(merged.configAppName).toBeUndefined(); expect(merged.appRoot).toBeUndefined(); @@ -442,16 +452,17 @@ describe("mergeComputeDeployInputs", () => { }); describe("mergeComputeLocalInputs", () => { - const target: ComputeDeployTarget = { + const target = { key: "api", name: null, + region: null, root: "apps/api", framework: "hono", entry: "src/index.ts", httpPort: 8080, envInputs: [], build: null, - }; + } as ComputeDeployTarget; it("maps the configured framework to a local build type", () => { expect(computeFrameworkToBuildType("nextjs")).toBe("nextjs"); diff --git a/packages/cli/tests/deploy-plan.test.ts b/packages/cli/tests/deploy-plan.test.ts index ec32c8b8..61f686b7 100644 --- a/packages/cli/tests/deploy-plan.test.ts +++ b/packages/cli/tests/deploy-plan.test.ts @@ -19,6 +19,7 @@ function config( targets: keys.map((key) => ({ key, name: null, + region: null, root: key ? `apps/${key}` : null, framework: null, entry: null, @@ -34,6 +35,7 @@ const noPerAppInputs = { framework: undefined, entrypoint: undefined, httpPort: undefined, + region: undefined, envAssignments: undefined, appIdEnvVar: { name: "PRISMA_APP_ID", value: undefined }, }; @@ -114,6 +116,7 @@ describe("perAppInputsForDeployAll", () => { framework: "hono", entrypoint: "src/index.ts", httpPort: "8080", + region: "us-west-1", envAssignments: ["KEY=value"], appIdEnvVar: { name: "PRISMA_APP_ID", value: "app_1" }, }), @@ -122,6 +125,7 @@ describe("perAppInputsForDeployAll", () => { "--framework", "--entry", "--http-port", + "--region", "--env", "PRISMA_APP_ID", ]); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 916180b1..dccd4c79 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,8 +24,8 @@ importers: specifier: ^1.5.0 version: 1.5.0 '@prisma/compute-sdk': - specifier: 0.30.0 - version: 0.30.0(@prisma/management-api-sdk@1.44.0)(rollup@4.61.0) + specifier: 0.31.0 + version: 0.31.0(@prisma/management-api-sdk@1.44.0)(rollup@4.62.2) '@prisma/credentials-store': specifier: ^7.8.0 version: 7.8.0 @@ -548,8 +548,8 @@ packages: '@oxc-project/types@0.127.0': resolution: {integrity: sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==} - '@prisma/compute-sdk@0.30.0': - resolution: {integrity: sha512-jWTH1z8oUjBFQxpt6EoBfQFVOJ+YYVpr5CHIBPjqNtXioXqB1hSMsePd7SnKl2VrA3jienrvv3KmL3glLSmhSw==} + '@prisma/compute-sdk@0.31.0': + resolution: {integrity: sha512-V2av8c6qVrWqYug6qL82qBnyep+mFq0FP3MANSGalISoSUHwiQbXIWVoT7HnM6kaXYa6d1aU4Sb+1iR8GnQ6DA==} engines: {node: '>=18.0.0'} peerDependencies: '@prisma/management-api-sdk': ^1.44.0 @@ -670,141 +670,141 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.61.0': - resolution: {integrity: sha512-dnxczajOqt0gesZlN5pGQ1s1imQVrsmCw5G2Ci4oM+0WvNz3pyRnlWrT7McoZIb8VlFwCawdmbWRmxRn7HI+VQ==} + '@rollup/rollup-android-arm-eabi@4.62.2': + resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.61.0': - resolution: {integrity: sha512-Bp3JpGP00Vu3f238ivRrjf7z3xSzVPXqCmaJYA9t2c+c8vKYvOzmXF7LkkeUalTEGd6cZcSWe+PFIP3Vy48fRg==} + '@rollup/rollup-android-arm64@4.62.2': + resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.61.0': - resolution: {integrity: sha512-zaYIpr670mUmmZ1tVzUFplbQbG7h3Gugx3L5FoqhsC2m/YnLlR1a7zVLmXNPy+iY1tFPEbNG+HHBXZGyId0G5w==} + '@rollup/rollup-darwin-arm64@4.62.2': + resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.61.0': - resolution: {integrity: sha512-+P49fvkv2dSoeevUW+lgZ/I2JHSsJCK1Lyjj7Cu6E4UHG4tS9XIefzIjo5qhgELjAclnen1rLzK2PMKJdo+Dyg==} + '@rollup/rollup-darwin-x64@4.62.2': + resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.61.0': - resolution: {integrity: sha512-l3FAAOyKJXH2ea6KNFN+MMgC/rnE94YGLXs2ehYqDcCoHt1DpvgWX75BhUJxN38XojP7Ul+4H8PRn7EdyqSDrw==} + '@rollup/rollup-freebsd-arm64@4.62.2': + resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.61.0': - resolution: {integrity: sha512-VokPN3TSctKj65cyCNPaUh4vMFA8awxOot/0sp+4J7ZlNRKQEhXhawqPwajoi8H5ZFt61i0ugZJuTKXBjGJ17Q==} + '@rollup/rollup-freebsd-x64@4.62.2': + resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.61.0': - resolution: {integrity: sha512-DxH0P3wxm+Yzs/p3zrk9dw1rURu8p0Nv5+MRK/L7OtnLNg5rLZraSBFZ8iUXOd9f2BlhJyEpIZUH/emjq4UJ4g==} + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==} cpu: [arm] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm-musleabihf@4.61.0': - resolution: {integrity: sha512-T6ZvMNe84kAz6TBWHC7hGAoEtzP1LWYw/AqayGWEF6uISt3Abk/st06LqRD9THd7Xz3NxzurUpzAuEAUbZf+nw==} + '@rollup/rollup-linux-arm-musleabihf@4.62.2': + resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==} cpu: [arm] os: [linux] libc: [musl] - '@rollup/rollup-linux-arm64-gnu@4.61.0': - resolution: {integrity: sha512-q/4hzvQkDs8b4jIBab1pnLiiM0ayTZsN2amBFPDzuyZxjEd4wDwx0UJFYM3cOZzSf5Kw8fnWSprJzIBMkcR44Q==} + '@rollup/rollup-linux-arm64-gnu@4.62.2': + resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==} cpu: [arm64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.61.0': - resolution: {integrity: sha512-vvYWX3akdEAY6km+9wAqFDnk6pQsbJKVnj7xawcvs/+fdlYBGp+U+Qq/lLfpIxYIZvZLHMAKD9HLdacSx/r3dw==} + '@rollup/rollup-linux-arm64-musl@4.62.2': + resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==} cpu: [arm64] os: [linux] libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.61.0': - resolution: {integrity: sha512-DePa5cqOxDP/Zp0VOXpeWaGew5iIv5DXp9NYbzkX5PFQyWVX9184WCTh3hvr/7lhXo8ZVlbFLkz8+o/q1dU6gA==} + '@rollup/rollup-linux-loong64-gnu@4.62.2': + resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==} cpu: [loong64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-loong64-musl@4.61.0': - resolution: {integrity: sha512-LV8aWMB8UChglMCEzs7RkN0GsH29RJaLLqwm9fCIjlqwxQTiWAqNcc7wjBkH31hV0PU/yVxGYvrYsgfea2qw6g==} + '@rollup/rollup-linux-loong64-musl@4.62.2': + resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==} cpu: [loong64] os: [linux] libc: [musl] - '@rollup/rollup-linux-ppc64-gnu@4.61.0': - resolution: {integrity: sha512-QoNSnwQtaeNu5grdBbsL0tt1uyl5EnS8DA8Mr3nluMXbhdQNyhN+G4tBax7VCdxLKj8YJ0/4OO9Ho84jMnJtKA==} + '@rollup/rollup-linux-ppc64-gnu@4.62.2': + resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==} cpu: [ppc64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-ppc64-musl@4.61.0': - resolution: {integrity: sha512-/zZp5MKapIIApE8trN8qLGNSiRN9TUoaUZ1cmVu4XnVdd5LQLOXTtyi+vtfUbNnT3iyjzpPqYeKXmvJ+gJGYWw==} + '@rollup/rollup-linux-ppc64-musl@4.62.2': + resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==} cpu: [ppc64] os: [linux] libc: [musl] - '@rollup/rollup-linux-riscv64-gnu@4.61.0': - resolution: {integrity: sha512-RbrzcD3aJ1k3UbtMRRBNwojdVVyXjuVAFTfn/xPa6EEl6GE9Sm/akPgFTb9aAC9pMKGJ6CtWxaGrqWcabH+ySg==} + '@rollup/rollup-linux-riscv64-gnu@4.62.2': + resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==} cpu: [riscv64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-riscv64-musl@4.61.0': - resolution: {integrity: sha512-ZF+onDsBso8PJf1XaG9lB+O9RnBpKGnY6OrzC4CSHrtC1jb6jWLTKK4bRqdoCXHd22gyr2hiYmEAm8Wns/BOCw==} + '@rollup/rollup-linux-riscv64-musl@4.62.2': + resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==} cpu: [riscv64] os: [linux] libc: [musl] - '@rollup/rollup-linux-s390x-gnu@4.61.0': - resolution: {integrity: sha512-Atk0aSIk5Zx2Wuh9dgRQgLP0Koc8hOeYpbWryMXyk8G8/HmPkwPPkMqIIDhrXHHYqfUzSJA/I7IWSBv8xSmRBA==} + '@rollup/rollup-linux-s390x-gnu@4.62.2': + resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==} cpu: [s390x] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.61.0': - resolution: {integrity: sha512-0uMOcf3eZ5K+K4cYHkdxShFMPlPXCOdfDFEFn9dNYAEEd2cVvmOfH7zFgRVoDgmtQ1m9k5q7qfrHzyMAubKYUA==} + '@rollup/rollup-linux-x64-gnu@4.62.2': + resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==} cpu: [x64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.61.0': - resolution: {integrity: sha512-mvFtE4A/t/7hRJ7X8Ozmu8FsIkAUat2nzl12pgU337BRmq87AQUJztwHz2Zv5/tjo9/C95E66CK03SI/ToEDJw==} + '@rollup/rollup-linux-x64-musl@4.62.2': + resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==} cpu: [x64] os: [linux] libc: [musl] - '@rollup/rollup-openbsd-x64@4.61.0': - resolution: {integrity: sha512-z9b9+aTxvt8n2rNltMPvyaUfB8NJ+CVyOrGK/MdIKHx7B+lXmZpm/XbRsU7Rpf3fRqJ2uS6mBJiJveCtq8LHDg==} + '@rollup/rollup-openbsd-x64@4.62.2': + resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==} cpu: [x64] os: [openbsd] - '@rollup/rollup-openharmony-arm64@4.61.0': - resolution: {integrity: sha512-jXaXFqKMehsOc+g8R6oo33RRC6w07G9jDBxAE5eAKX7mOcCbZloYIPNhfG9Wl+P9O9IWHFO4OJgPi1Ml2qkt7w==} + '@rollup/rollup-openharmony-arm64@4.62.2': + resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.61.0': - resolution: {integrity: sha512-OXNWVFocS2IA4+QplhTZZ2a+8hPZR7T8KuozsNmJKK8y7cp83StHvGksfHzPG3wczWTczyWHVQuqeiTUbjiyBg==} + '@rollup/rollup-win32-arm64-msvc@4.62.2': + resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.61.0': - resolution: {integrity: sha512-AlAbNtBO637LxSldqV43z0FfXoGfl2TW1DgAg/bs7aQswFbDewz2SJm3BUhiGfbOVtW571xbc9p+REdxhyN/Eg==} + '@rollup/rollup-win32-ia32-msvc@4.62.2': + resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.61.0': - resolution: {integrity: sha512-QRSrQXyJ1M4tjNXdR0/G/IgV6lzfQQJYBjlWIEYkY2Xs86DRl/iEpQ4blMDjJxSl7n19eDKKXMg0AmuBVYy8pQ==} + '@rollup/rollup-win32-x64-gnu@4.62.2': + resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.61.0': - resolution: {integrity: sha512-tkuFxhvKO/HlGd0VsINF6vHSYH8AF8W0TcNxKDK6JZmrehngFj78pToc8iemtnvwilDjs2G/qSzYFhe9U8q+fw==} + '@rollup/rollup-win32-x64-msvc@4.62.2': + resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==} cpu: [x64] os: [win32] @@ -916,16 +916,16 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - bare-events@2.8.3: - resolution: {integrity: sha512-HdUm8EMQBLaJvGUdidNNbqpA1kYkwNcb+MYxkxCLAPJGQzlv9J0C24h8V65Z4c5GLd/JEALDvpFCQgpLJqc0zw==} + bare-events@2.9.1: + resolution: {integrity: sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg==} peerDependencies: bare-abort-controller: '*' peerDependenciesMeta: bare-abort-controller: optional: true - bare-fs@4.7.1: - resolution: {integrity: sha512-WDRsyVN52eAx/lBamKD6uyw8H4228h/x0sGGGegOamM2cd7Pag88GfMQalobXI+HaEUxpCkbKQUDOQqt9wawRw==} + bare-fs@4.7.2: + resolution: {integrity: sha512-aTvMFUWkBmjzKtEQMDGGDNF8bkfpD5N1b/FCwt7A3wrU4t1o/e/85Wzkluh6JlODCjqVESYCkQCdTXqZ9G7VFg==} engines: {bare: '>=1.16.0'} peerDependencies: bare-buffer: '*' @@ -940,8 +940,8 @@ packages: bare-path@3.0.1: resolution: {integrity: sha512-ghj2DSK/2e99a1anTVPCV4m4YIYtrbXhfM7V3D7XZLOTsybnYyaJloymGqssQc8l/or0UoDyRtNQkmkEF/ysgQ==} - bare-stream@2.13.1: - resolution: {integrity: sha512-Vp0cnjYyrEC4whYTymQ+YZi6pBpfiICZO3cfRG8sy67ZNWe951urv1x4eW1BKNngw3U+3fPYb5JQvHbCtxH7Ow==} + bare-stream@2.13.3: + resolution: {integrity: sha512-Kc+brLqvEqGkjyfiwJmImAOqLZL7OsoLKuavx+hJjgVV3nLTOjloJyPMFxjUPerGGHrNH0fLU06jjykMLWrERQ==} peerDependencies: bare-abort-controller: '*' bare-buffer: '*' @@ -954,8 +954,8 @@ packages: bare-events: optional: true - bare-url@2.4.3: - resolution: {integrity: sha512-Kccpc7ACfXaxfeInfqKcZtW4pT5YBn1mesc4sCsun6sRwtbJ4h+sNOaksUpYEJUKfN65YWC6Bw2OJEFiKxq8nQ==} + bare-url@2.4.5: + resolution: {integrity: sha512-K+y9xF1tN+CdPu4qWwr0QiK1Al07eFPGYK5M2pDXcmHdMdgC/tT/bpmMe1hrmRHaidKLkXrC+cRNYf3XVDUhSQ==} better-result@2.9.2: resolution: {integrity: sha512-WIFoBPCdnTOdk9inkE1ZRvCZ4P0CpSkAiLlchC65N7n9DcjZ3NhqkBOlafzpOVnO8ixyi37kicmSJ3ENhPZl7Q==} @@ -1177,8 +1177,8 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.12: - resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} + nanoid@3.3.15: + resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -1277,8 +1277,8 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - rollup@4.61.0: - resolution: {integrity: sha512-T9mWdbWfQtp0B5lv/HX+wrhYsmXRlcWnXXmJbXqKJhlRaoS6KMhq0gpyzW4UJfclcxrEdLnTgjT2NjruLONu0g==} + rollup@4.62.2: + resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -1291,6 +1291,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -1307,8 +1312,8 @@ packages: std-env@4.1.0: resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} - streamx@2.26.0: - resolution: {integrity: sha512-VvNG1K72Po/xwJzxZFnZ++Tbrv4lwSptsbkFuzXCJAYZvCK5nnxsvXU6ajqkv7chyiI1Y0YXq2Jh8Iy8Y7NF/A==} + streamx@2.28.0: + resolution: {integrity: sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw==} string-width@8.2.1: resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} @@ -1823,7 +1828,7 @@ snapshots: https-proxy-agent: 7.0.6 node-fetch: 2.7.0 nopt: 8.1.0 - semver: 7.8.1 + semver: 7.8.5 tar: 7.5.16 transitivePeerDependencies: - encoding @@ -1838,10 +1843,10 @@ snapshots: '@oxc-project/types@0.127.0': {} - '@prisma/compute-sdk@0.30.0(@prisma/management-api-sdk@1.44.0)(rollup@4.61.0)': + '@prisma/compute-sdk@0.31.0(@prisma/management-api-sdk@1.44.0)(rollup@4.62.2)': dependencies: '@prisma/management-api-sdk': 1.44.0 - '@vercel/nft': 1.10.2(rollup@4.61.0) + '@vercel/nft': 1.10.2(rollup@4.62.2) better-result: 2.9.2 jiti: 2.7.0 magicast: 0.5.3 @@ -1921,87 +1926,87 @@ snapshots: '@rolldown/pluginutils@1.0.0-rc.17': {} - '@rollup/pluginutils@5.4.0(rollup@4.61.0)': + '@rollup/pluginutils@5.4.0(rollup@4.62.2)': dependencies: '@types/estree': 1.0.9 estree-walker: 2.0.2 picomatch: 4.0.4 optionalDependencies: - rollup: 4.61.0 + rollup: 4.62.2 - '@rollup/rollup-android-arm-eabi@4.61.0': + '@rollup/rollup-android-arm-eabi@4.62.2': optional: true - '@rollup/rollup-android-arm64@4.61.0': + '@rollup/rollup-android-arm64@4.62.2': optional: true - '@rollup/rollup-darwin-arm64@4.61.0': + '@rollup/rollup-darwin-arm64@4.62.2': optional: true - '@rollup/rollup-darwin-x64@4.61.0': + '@rollup/rollup-darwin-x64@4.62.2': optional: true - '@rollup/rollup-freebsd-arm64@4.61.0': + '@rollup/rollup-freebsd-arm64@4.62.2': optional: true - '@rollup/rollup-freebsd-x64@4.61.0': + '@rollup/rollup-freebsd-x64@4.62.2': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.61.0': + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.61.0': + '@rollup/rollup-linux-arm-musleabihf@4.62.2': optional: true - '@rollup/rollup-linux-arm64-gnu@4.61.0': + '@rollup/rollup-linux-arm64-gnu@4.62.2': optional: true - '@rollup/rollup-linux-arm64-musl@4.61.0': + '@rollup/rollup-linux-arm64-musl@4.62.2': optional: true - '@rollup/rollup-linux-loong64-gnu@4.61.0': + '@rollup/rollup-linux-loong64-gnu@4.62.2': optional: true - '@rollup/rollup-linux-loong64-musl@4.61.0': + '@rollup/rollup-linux-loong64-musl@4.62.2': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.61.0': + '@rollup/rollup-linux-ppc64-gnu@4.62.2': optional: true - '@rollup/rollup-linux-ppc64-musl@4.61.0': + '@rollup/rollup-linux-ppc64-musl@4.62.2': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.61.0': + '@rollup/rollup-linux-riscv64-gnu@4.62.2': optional: true - '@rollup/rollup-linux-riscv64-musl@4.61.0': + '@rollup/rollup-linux-riscv64-musl@4.62.2': optional: true - '@rollup/rollup-linux-s390x-gnu@4.61.0': + '@rollup/rollup-linux-s390x-gnu@4.62.2': optional: true - '@rollup/rollup-linux-x64-gnu@4.61.0': + '@rollup/rollup-linux-x64-gnu@4.62.2': optional: true - '@rollup/rollup-linux-x64-musl@4.61.0': + '@rollup/rollup-linux-x64-musl@4.62.2': optional: true - '@rollup/rollup-openbsd-x64@4.61.0': + '@rollup/rollup-openbsd-x64@4.62.2': optional: true - '@rollup/rollup-openharmony-arm64@4.61.0': + '@rollup/rollup-openharmony-arm64@4.62.2': optional: true - '@rollup/rollup-win32-arm64-msvc@4.61.0': + '@rollup/rollup-win32-arm64-msvc@4.62.2': optional: true - '@rollup/rollup-win32-ia32-msvc@4.61.0': + '@rollup/rollup-win32-ia32-msvc@4.62.2': optional: true - '@rollup/rollup-win32-x64-gnu@4.61.0': + '@rollup/rollup-win32-x64-gnu@4.62.2': optional: true - '@rollup/rollup-win32-x64-msvc@4.61.0': + '@rollup/rollup-win32-x64-msvc@4.62.2': optional: true '@standard-schema/spec@1.1.0': {} @@ -2026,10 +2031,10 @@ snapshots: dependencies: undici-types: 6.21.0 - '@vercel/nft@1.10.2(rollup@4.61.0)': + '@vercel/nft@1.10.2(rollup@4.62.2)': dependencies: '@mapbox/node-pre-gyp': 2.0.3 - '@rollup/pluginutils': 5.4.0(rollup@4.61.0) + '@rollup/pluginutils': 5.4.0(rollup@4.62.2) acorn: 8.17.0 acorn-import-attributes: 1.9.5(acorn@8.17.0) async-sema: 3.1.1 @@ -2116,14 +2121,14 @@ snapshots: balanced-match@4.0.4: {} - bare-events@2.8.3: {} + bare-events@2.9.1: {} - bare-fs@4.7.1: + bare-fs@4.7.2: dependencies: - bare-events: 2.8.3 + bare-events: 2.9.1 bare-path: 3.0.1 - bare-stream: 2.13.1(bare-events@2.8.3) - bare-url: 2.4.3 + bare-stream: 2.13.3(bare-events@2.9.1) + bare-url: 2.4.5 fast-fifo: 1.3.2 transitivePeerDependencies: - bare-abort-controller @@ -2135,16 +2140,17 @@ snapshots: dependencies: bare-os: 3.9.1 - bare-stream@2.13.1(bare-events@2.8.3): + bare-stream@2.13.3(bare-events@2.9.1): dependencies: - streamx: 2.26.0 + b4a: 1.8.1 + streamx: 2.28.0 teex: 1.0.1 optionalDependencies: - bare-events: 2.8.3 + bare-events: 2.9.1 transitivePeerDependencies: - react-native-b4a - bare-url@2.4.3: + bare-url@2.4.5: dependencies: bare-path: 3.0.1 @@ -2269,7 +2275,7 @@ snapshots: events-universal@1.0.1: dependencies: - bare-events: 2.8.3 + bare-events: 2.9.1 transitivePeerDependencies: - bare-abort-controller @@ -2361,7 +2367,7 @@ snapshots: ms@2.1.3: {} - nanoid@3.3.12: {} + nanoid@3.3.15: {} node-fetch@2.7.0: dependencies: @@ -2409,7 +2415,7 @@ snapshots: postcss@8.5.15: dependencies: - nanoid: 3.3.12 + nanoid: 3.3.15 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -2460,41 +2466,43 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.17 '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.17 - rollup@4.61.0: + rollup@4.62.2: dependencies: '@types/estree': 1.0.9 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.61.0 - '@rollup/rollup-android-arm64': 4.61.0 - '@rollup/rollup-darwin-arm64': 4.61.0 - '@rollup/rollup-darwin-x64': 4.61.0 - '@rollup/rollup-freebsd-arm64': 4.61.0 - '@rollup/rollup-freebsd-x64': 4.61.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.61.0 - '@rollup/rollup-linux-arm-musleabihf': 4.61.0 - '@rollup/rollup-linux-arm64-gnu': 4.61.0 - '@rollup/rollup-linux-arm64-musl': 4.61.0 - '@rollup/rollup-linux-loong64-gnu': 4.61.0 - '@rollup/rollup-linux-loong64-musl': 4.61.0 - '@rollup/rollup-linux-ppc64-gnu': 4.61.0 - '@rollup/rollup-linux-ppc64-musl': 4.61.0 - '@rollup/rollup-linux-riscv64-gnu': 4.61.0 - '@rollup/rollup-linux-riscv64-musl': 4.61.0 - '@rollup/rollup-linux-s390x-gnu': 4.61.0 - '@rollup/rollup-linux-x64-gnu': 4.61.0 - '@rollup/rollup-linux-x64-musl': 4.61.0 - '@rollup/rollup-openbsd-x64': 4.61.0 - '@rollup/rollup-openharmony-arm64': 4.61.0 - '@rollup/rollup-win32-arm64-msvc': 4.61.0 - '@rollup/rollup-win32-ia32-msvc': 4.61.0 - '@rollup/rollup-win32-x64-gnu': 4.61.0 - '@rollup/rollup-win32-x64-msvc': 4.61.0 + '@rollup/rollup-android-arm-eabi': 4.62.2 + '@rollup/rollup-android-arm64': 4.62.2 + '@rollup/rollup-darwin-arm64': 4.62.2 + '@rollup/rollup-darwin-x64': 4.62.2 + '@rollup/rollup-freebsd-arm64': 4.62.2 + '@rollup/rollup-freebsd-x64': 4.62.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.2 + '@rollup/rollup-linux-arm-musleabihf': 4.62.2 + '@rollup/rollup-linux-arm64-gnu': 4.62.2 + '@rollup/rollup-linux-arm64-musl': 4.62.2 + '@rollup/rollup-linux-loong64-gnu': 4.62.2 + '@rollup/rollup-linux-loong64-musl': 4.62.2 + '@rollup/rollup-linux-ppc64-gnu': 4.62.2 + '@rollup/rollup-linux-ppc64-musl': 4.62.2 + '@rollup/rollup-linux-riscv64-gnu': 4.62.2 + '@rollup/rollup-linux-riscv64-musl': 4.62.2 + '@rollup/rollup-linux-s390x-gnu': 4.62.2 + '@rollup/rollup-linux-x64-gnu': 4.62.2 + '@rollup/rollup-linux-x64-musl': 4.62.2 + '@rollup/rollup-openbsd-x64': 4.62.2 + '@rollup/rollup-openharmony-arm64': 4.62.2 + '@rollup/rollup-win32-arm64-msvc': 4.62.2 + '@rollup/rollup-win32-ia32-msvc': 4.62.2 + '@rollup/rollup-win32-x64-gnu': 4.62.2 + '@rollup/rollup-win32-x64-msvc': 4.62.2 fsevents: 2.3.3 run-applescript@7.1.0: {} semver@7.8.1: {} + semver@7.8.5: {} + siginfo@2.0.0: {} sisteransi@1.0.5: {} @@ -2505,7 +2513,7 @@ snapshots: std-env@4.1.0: {} - streamx@2.26.0: + streamx@2.28.0: dependencies: events-universal: 1.0.1 fast-fifo: 1.3.2 @@ -2526,9 +2534,9 @@ snapshots: tar-stream@3.2.0: dependencies: b4a: 1.8.1 - bare-fs: 4.7.1 + bare-fs: 4.7.2 fast-fifo: 1.3.2 - streamx: 2.26.0 + streamx: 2.28.0 transitivePeerDependencies: - bare-abort-controller - bare-buffer @@ -2544,7 +2552,7 @@ snapshots: teex@1.0.1: dependencies: - streamx: 2.26.0 + streamx: 2.28.0 transitivePeerDependencies: - bare-abort-controller - react-native-b4a @@ -2627,7 +2635,7 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 postcss: 8.5.15 - rollup: 4.61.0 + rollup: 4.62.2 tinyglobby: 0.2.17 optionalDependencies: '@types/node': 22.19.19