import * as Effect from "effect/Effect"; import * as Redacted from "effect/Redacted"; import type * as rolldown from "rolldown"; import * as Bundle from "../Bundle/Bundle.ts"; import type { InputProps } from "../Input.ts"; import { Platform, type Main, type PlatformProps } from "../Platform.ts"; import * as Provider from "../Provider.ts"; import { Resource } from "../Resource.ts"; import type * as Server from "../Server/index.ts"; import { type PrismaManagementClient } from "./Client.ts"; import { type ComputeAutoBuildFramework } from "./ComputeBuild.ts"; import type { Project } from "./Project.ts"; import type { Providers } from "./Providers.ts"; import type { PrismaRegionId } from "./Types.ts"; declare const ComputeTypeId: "Prisma.Compute"; type ComputeTypeId = typeof ComputeTypeId; export interface ComputeCommandBuild { /** * Shell command that creates the deployable output directory. */ command: string; /** * Working directory for the build command. * * @default path */ cwd?: string; /** * Build output directory, relative to `cwd`. */ outdir: string; /** * Entrypoint inside `outdir`. */ entrypoint?: string; /** * Environment variables supplied to the build command. * Ambient `PRISMA_SERVICE_TOKEN` and `PRISMA_API_TOKEN` credentials are not * inherited; include one here explicitly only when the application build * genuinely needs Prisma Management API access. * * Plain strings are persisted in Alchemy state. Wrap secrets with * `Redacted.make(secret)`; Prisma-side encryption does not protect a value * already stored in Alchemy state. * * ```typescript * env: { NPM_TOKEN: Redacted.make(process.env.NPM_TOKEN!) } * ``` */ env?: Record | undefined>; /** * Maximum bytes retained from each build output stream. * * @default 1048576 (1 MiB) */ outputLimitBytes?: number; /** * Maximum wall-clock time for the build command. * * @default 900 (15 minutes) */ timeoutSeconds?: number; } export interface ComputeAutoBuild { /** * Auto-detect a Prisma Compute build strategy, or force one framework. */ type: "auto"; /** * Framework build strategy. * * @default "auto" */ framework?: ComputeAutoBuildFramework; /** * Environment variables supplied to the build command. * Ambient `PRISMA_SERVICE_TOKEN` and `PRISMA_API_TOKEN` credentials are not * inherited; include one here explicitly only when the application build * genuinely needs Prisma Management API access. * * Plain strings are persisted in Alchemy state. Wrap secrets with * `Redacted.make(secret)`. * * ```typescript * env: { NPM_TOKEN: Redacted.make(process.env.NPM_TOKEN!) } * ``` */ env?: Record | undefined>; /** * Maximum bytes retained from each framework build output stream. * * @default 1048576 (1 MiB) */ outputLimitBytes?: number; /** * Maximum wall-clock time for the framework build command. * * @default 900 (15 minutes) */ timeoutSeconds?: number; } export type ComputeBuild = ComputeCommandBuild | ComputeAutoBuild; export interface ComputeBundleOptions { /** * Rolldown input options for effect-native Compute bundles. */ input?: Partial; /** * Rolldown output options for effect-native Compute bundles. */ output?: Partial; /** * Additional Alchemy bundle options for effect-native Compute bundles. */ extra?: Bundle.BundleExtraOptions; } export interface ComputeDev { /** * Local command to run during `alchemy dev`. */ command?: string; /** * Working directory for the dev command. * * @default path */ cwd?: string; /** * Local development port. */ port?: number; /** * Explicit local URL to expose in the resource output. */ url?: string; /** * Extra environment variables for the dev command. * Plain strings are persisted in Alchemy state. Wrap secrets with * `Redacted.make(secret)`. */ env?: Record | undefined>; } export interface ComputeHealthCheck { /** * Absolute application path to probe after the deployment starts and after * promotion. * * @example "/api/health" */ path: string; /** * Exact HTTP status codes that indicate readiness. When omitted, any 2xx * response is healthy. * * @default Any status from 200 through 299 */ statusCodes?: readonly number[]; } export interface ComputeProps extends PlatformProps { /** * Project ID or `project.projectId` output that owns the App. */ project: string | Project; /** * App display name. If omitted, Alchemy generates a stable physical name. */ appName?: string; /** * Region where the App is placed. * * @default The project's default region, falling back to "us-east-1" */ regionId?: PrismaRegionId; /** * Branch ID to attach the App to. Mutually exclusive with branchGitName. * If both branch fields are omitted, Alchemy attaches to the project's * current default branch. */ branchId?: string; /** * Branch git name to attach the App to. Mutually exclusive with branchId. * * @default The project's current default branch */ branchGitName?: string; /** * Application directory used for pre-built artifacts and build commands. * * @default "." */ path?: string; /** * Additional artifact-relative files or directories to exclude from path * deployments. `*` and `**` wildcards are supported; absolute paths, * parent segments, and negated patterns are rejected. `.env*`, `.git`, and * `.alchemy` are always excluded. */ archiveIgnore?: readonly string[]; /** * Entrypoint relative to the deployed artifact directory. * If omitted, Alchemy reads `package.json#main`. */ entrypoint?: string; /** * Entry module for an effect-native Compute app. * * This is required when you pass an inline Effect implementation to * `Prisma.Compute`, and ignored for external path deployments. */ main?: string; /** * Exported symbol inside `main` for effect-native Compute apps. * * @default "default" */ handler?: string; /** * Bundler options for effect-native Compute apps. */ bundle?: ComputeBundleOptions; /** * Effect-native runtime exports populated by the Platform constructor. * * @internal */ exports?: string[] | Record; /** * Build command and output directory. Set to `"auto"` or `{ type: "auto" }` * to use Prisma Compute-style framework detection for Next.js, Nuxt, Astro, * TanStack Start, or Bun. Set to `false` to upload `path` as a pre-built * artifact. */ build?: ComputeBuild | false | "auto"; /** * Path to a pre-created `tar.gz` artifact file. When supplied, Alchemy reads * and uploads it directly. */ artifactPath?: string; /** * HTTP port exposed by the application. * * @default 8080 */ port?: number; /** * Runtime environment variables to sync through Prisma's environment * variable API before creating a new deployment. Set a value to `null` * to delete that variable. * * Plain strings are persisted in Alchemy state. For secrets, use * `Redacted.make(secret)`; encryption in the Prisma Management API does not * protect a plain value already recorded in Alchemy state. * * The Management API exposes neither an idempotency key nor ownership * metadata for environment variables, and reads return redacted values. If * a process crashes after Prisma commits a create but before Alchemy saves * its returned ID, the next deploy safely refuses to claim that natural-key * match. Use standalone `Prisma.EnvironmentVariable` resources for critical * keys that need independent lifecycle management and explicit adoption. * * ```typescript * env: { * LOG_LEVEL: "info", * API_TOKEN: Redacted.make(process.env.API_TOKEN!), * } * ``` */ env?: Record | null | undefined>; /** * Prisma environment variable class used by the `env` convenience property. * * @default "production" */ envClass?: "production" | "preview"; /** * Create the next deployment by reusing the previous code artifact. * * @default false */ skipCodeUpload?: boolean; /** * Start the created/reused deployment. * Set `skipPromote: true` when disabling start. * * @default true */ start?: boolean; /** * Do not promote the deployment to the stable App endpoint. * * @default false */ skipPromote?: boolean; /** * Delete the previously promoted deployment after the new one is promoted. * * @default false */ destroyOldDeployment?: boolean; /** * Poll timeout while waiting for start/stop. * * @default 120 */ timeoutSeconds?: number; /** * Poll interval while waiting for start/stop. * * @default 1000 */ pollIntervalMs?: number; /** * Verify that Prisma's public preview/App URL has reached the edge after * the Management API reports the deployment as running. * * @default true */ verifyUrl?: boolean; /** * Optional application-level health check. Without this option, URL * verification only waits for Prisma edge routing to stop returning its * platform-level service-not-found response. With this option, Alchemy also * sends a public GET to the preview URL before promotion and to the stable * App URL afterward. Redirects are not followed. Each probe phase gets the * full `urlReadinessTimeoutSeconds` budget. * * Health checks run only during cloud deployment, not `alchemy dev`, and * cannot be combined with `verifyUrl: false` or `start: false`. */ healthCheck?: ComputeHealthCheck; /** * Maximum time to wait for Prisma's public URL to stop returning the * platform-level "Service not found" page. * * @default 60 */ urlReadinessTimeoutSeconds?: number; /** * Local development behavior for `alchemy dev`. */ dev?: ComputeDev; } export interface Compute extends Resource; /** * Prisma environment class used for the managed environment variable keys. */ environmentClass?: "production" | "preview"; /** * Branch ID used for managed preview branch environment overrides, or null * for project-level environment templates. */ environmentBranchId?: string | null; /** * Fingerprint of the uploaded artifact/reused artifact inputs and the * branch attachment that Prisma resolves environment variables from. */ artifactHash: Redacted.Redacted | undefined; /** * Whether the app output represents a local dev process. */ local: boolean; }, { env?: Record | null | undefined>; }, Providers> { } export type ComputeRuntimeServices = Server.ProcessServices; export type ComputeShape = Main; export interface ComputeRuntimeContext extends Server.ProcessContext { readonly Type: ComputeTypeId; } export declare const isCompute: (value: unknown) => value is Compute; /** * Build and deploy an application to Prisma Compute. * * Prisma's create-deployment API exposes neither an idempotency key nor a * caller-defined recovery key. If the API commits a deployment but its create * response is lost before Alchemy persists the returned ID, that deployment * can remain orphaned and a later deploy may create another one. Alchemy does * not guess that the App's latest deployment is owned, because it could belong * to another actor. Use a durable, locked state backend and inspect the App's * deployment history after an interrupted create. * * ### Deploying an App * **Example:** Deploy a directory with an entrypoint * ```typescript * const app = yield* Prisma.Compute("api", { * project: project.projectId, * path: "./apps/api", * entrypoint: "server.ts", * port: 3000, * }); * ``` * * **Example:** Deploy an Effect-native HTTP app * ```typescript * export default Prisma.Compute( * "api", * { * project, * appName: "api", * main: import.meta.filename, * port: 8080, * }, * Effect.gen(function* () { * return { * fetch: Effect.succeed(HttpServerResponse.text("ok")), * }; * }), * ); * ``` * * ### Bundling & Tree-shaking * `main` is bundled with rolldown at deploy time. Top-level calls in the * `effect`, `@effect/*`, `alchemy`, `@alchemy.run/*`, and * `@distilled.cloud/*` packages receive `#__PURE__` annotations by * default, so anything the app doesn't use from those packages is * tree-shaken out of the bundle. Any other package — including your own * app — is left untouched unless you list it explicitly. * * **Example:** Treat additional packages as pure * Pass package names (or picomatch globs) via `bundle.extra.pure.packages` to * annotate them in addition to the defaults. * ```typescript * { * main: "./src/app.ts", * bundle: { * extra: { pure: { packages: ["my-lib", "@my-scope/*"] } }, * }, * } * ``` * * Listing a package annotates calls whose result is bound (variable * initializers, exports) — safe anywhere. If a listed package also * declares `"sideEffects": false` (or `[]`) in its `package.json`, that * combination opts it into full annotation: top-level calls whose result * is discarded (e.g. `router.on("/path", handler)` registrations) are * also marked pure and deleted under minification when unused. Only list * a `sideEffects: false` package if its modules really are free of * meaningful top-level side effects. The `effect`, `alchemy`, and * `@distilled.cloud` defaults declare exactly that, on purpose — their * modules are designed to be fully tree-shakeable. * * **Example:** Disable pure annotations * ```typescript * { * main: "./src/app.ts", * bundle: { extra: { pure: false } }, * } * ``` * * ### Runtime Bindings * **Example:** Bind a Prisma Connection * ```typescript * export default Prisma.Compute( * "api", * { * project, * appName: "api", * main: import.meta.filename, * }, * Effect.gen(function* () { * const db = yield* Prisma.Connect(connection); * const sql = yield* SQL.Postgres({ url: db.databaseUrl }); * * return { * fetch: Effect.gen(function* () { * const users = yield* sql`SELECT * FROM users`; * return yield* HttpServerResponse.json(users); * }), * }; * }).pipe(Effect.provide(Prisma.ConnectBinding)), * ); * ``` * * **Example:** Build before upload and replace old versions * ```typescript * const app = yield* Prisma.Compute("api", { * project: project.projectId, * path: "./apps/api", * build: { * command: "bun build src/server.ts --target bun --outdir dist", * outdir: "dist", * entrypoint: "server.js", * }, * port: 8080, * env: { * // Use this for a standalone Connection. A project's default database * // is injected by Prisma without an explicit DATABASE_URL entry. * DATABASE_URL: connection.databaseUrl, * }, * destroyOldDeployment: true, * }); * ``` * * **Example:** Auto-build a framework app * ```typescript * const app = yield* Prisma.Compute("api", { * project: project.projectId, * path: "./apps/web", * build: "auto", * destroyOldDeployment: true, * }); * ``` * * **Example:** Deploy a prebuilt tar.gz artifact * ```typescript * const app = yield* Prisma.Compute("api", { * project: project.projectId, * artifactPath: "./dist/app.tar.gz", * port: 8080, * }); * ``` * * ### Deployment Health * **Example:** Require application readiness before promotion * ```typescript * const app = yield* Prisma.Compute("api", { * project, * path: "./apps/api", * entrypoint: "server.ts", * healthCheck: { * path: "/api/health", * // Defaults to any 2xx response when omitted. * statusCodes: [200, 204], * }, * }); * ``` * * ### Local Development * **Example:** Run locally during alchemy dev * ```typescript * const app = yield* Prisma.Compute("api", { * project: project.projectId, * path: "./apps/api", * entrypoint: "server.ts", * dev: { * command: "bun run dev", * port: 3000, * }, * }); * ``` * * @resource */ export declare const Compute: Platform & { (id: string, props: InputProps | Effect.Effect, never, PropsReq>): Effect.Effect; }; export declare const waitForDeploymentUrl: (url: string | undefined, props: ComputeProps) => Effect.Effect; export declare const syncComputeEnvironment: (client: PrismaManagementClient, projectId: string, cls: "preview" | "production", env?: Record | null | undefined> | undefined, branchId?: string | null | undefined, ownedIds?: Readonly> | undefined) => Effect.Effect<{ synced: string[]; deleted: string[]; ownedIds: Record; }, unknown, never>; export declare const ComputeDevProvider: () => import("effect/Layer").Layer, never, any>; export declare const ComputeProvider: () => import("effect/Layer").Layer, never, any>; export {}; //# sourceMappingURL=Compute.d.ts.map