import { Effect } from 'effect'; import { HttpClient } from '@effect/platform'; import { Schema } from 'effect'; import { Scope } from 'effect'; /** A bundled, ready-to-ship function. */ export declare interface BuiltFunction { readonly name: string; /** Absolute path to the bundled entry file. */ readonly file: string; /** Absolute path to the output dir (entry + any sidecar files). */ readonly dir: string; readonly runtime?: ServerlessRuntimeHints; } /** * Cache policy for a deployed file, keyed off its path RELATIVE to the dist * root (POSIX separators). Hashed assets → 1-year immutable; HTML → no-store * revalidate; everything else → a short shared TTL. */ export declare const cachePolicyFor: (relPath: string) => FileCachePolicy; /** Cloudflare Workers platform shape (entry + esbuild recipe). */ export declare const cloudflarePlatform: ServerlessPlatform; /** IANA content-type for a filename (defaults to octet-stream). */ export declare const contentTypeFor: (path: string) => string; /** * Declare a serverless function. Validates the name (kebab-case, DNS-safe — it * becomes the deployed function id) and fills defaults (`method: 'POST'`, * `path: '/'`). The CLI's discovery picks up the DEFAULT export of a * `*.serverless.ts` file. */ export declare const defineServerless: (def: ServerlessDefinition) => ServerlessDefinition; /** esbuild knobs a target needs to bundle the entry for its runtime. */ export declare interface EsbuildHints { /** V8-isolate hosts (Cloudflare) → `browser`; Node hosts (Scaleway) → `node`. */ readonly platform: 'browser' | 'node' | 'neutral'; readonly format: 'esm' | 'cjs'; /** Export conditions (e.g. `['worker', 'browser']` for Workers). */ readonly conditions?: ReadonlyArray; /** Specifiers to keep external (not bundled) — usually empty (bundle all). */ readonly external?: ReadonlyArray; /** Prepended to the bundle (e.g. a Node shim). */ readonly banner?: string; /** Target ES level. */ readonly targetEs?: string; /** Output entry filename. Defaults to `index.mjs` (esm) / `index.js` (cjs). * Scaleway overrides it to `handler.js`: its runtime imports the handler by * appending `.js` to the handler-string's module part AND ships a * `package.json` with `"type":"module"`, so the bundle must be ESM-syntax * under a `.js` name — and `handler.js` matches Scaleway's DEFAULT handler * `handler.handle`, so a bare `scw function deploy` resolves it with no * explicit handler wiring. */ readonly entryFile?: string; } /** * Cache policy for a deployed file. The framework derives it once (hashed asset * vs HTML) and hands it to every provider, so cache behaviour is identical no * matter where you ship. */ export declare interface FileCachePolicy { readonly contentType: string; readonly cacheControl: string; /** True for content-hashed assets (immutable, long TTL). */ readonly immutable: boolean; } /** Self-hosted Node platform shape (entry + esbuild recipe). */ export declare const nodePlatform: ServerlessPlatform; /** Scaleway Serverless Functions platform shape (entry + esbuild recipe). */ export declare const scalewayPlatform: ServerlessPlatform; /** * Platform-agnostic per-invocation context handed to a handler. The framework * fills it from whatever the host passes — Cloudflare's `env` bindings + * `ExecutionContext`, Scaleway's `process.env`, etc. — so handler code never * branches on the platform. */ export declare interface ServerlessContext { /** Env vars / secrets injected by the platform. Cloudflare → the worker `env` * bindings; Scaleway / Node → `process.env`. */ readonly env: Record; /** The raw incoming Web `Request` (method, url, headers) for advanced use. */ readonly request: Request; /** Schedule work that outlives the response — Cloudflare * `ExecutionContext.waitUntil`; a best-effort fire-and-forget elsewhere. */ readonly waitUntil: (promise: Promise) => void; } /** * A serverless function definition. The handler is Effect-first and may require * `HttpClient` (provided by the framework's base layer); decode/encode of the * JSON wire body is driven by the `input`/`output` schemas. */ export declare interface ServerlessDefinition { /** Deployment identifier — kebab-case, DNS-safe (it names the deployed * function/worker). */ readonly name: string; /** HTTP method the function answers on (default `POST`). A `GET` reads its * input from the query string; everything else from the JSON body. */ readonly method?: ServerlessMethod; /** Path the function answers on within its host (default `/`). */ readonly path?: string; /** Decodes the request body/query into the handler's typed input. */ readonly input: Schema.Schema; /** Encodes the handler's result into the JSON response body. */ readonly output: Schema.Schema; /** The work. Effect-first; may `yield* HttpClient.HttpClient` and use scoped * effects (e.g. `http.get(url)` + reading the body) directly — the framework * runs the handler inside a `Scope`, so you never write `Effect.scoped`. */ readonly handler: (input: I, ctx: ServerlessContext) => Effect.Effect; /** Deploy hints (memory / timeout / region / scale). */ readonly runtime?: ServerlessRuntimeHints; } /** Resolved deploy config — env-sourced credentials + per-target options. The * CLI assembles it from flags + env; each provider reads the keys it needs. */ export declare interface ServerlessDeployConfig { readonly env: Record; /** Free-form per-target options (account id, region, project id, …). */ readonly options?: Record; /** When true, do everything EXCEPT the final upload (print the plan). */ readonly dryRun?: boolean; } /** Thrown by a target's `deploy` when shipping fails (missing creds, API * error, bundle too large, …). */ export declare class ServerlessDeployError extends ServerlessDeployError_base { } declare const ServerlessDeployError_base: Schema.TaggedErrorClass; } & { target: typeof Schema.String; message: typeof Schema.String; detail: Schema.optional; }>; export declare interface ServerlessDeployResult { readonly target: string; readonly name: string; /** The deployed function's public URL, when the provider returns one. */ readonly url?: string; /** Provider-side id of the function/worker. */ readonly id?: string; } /** Fail a handler with this to control the HTTP status (otherwise → 500). */ export declare class ServerlessHttpError extends ServerlessHttpError_base { } declare const ServerlessHttpError_base: Schema.TaggedErrorClass; } & { status: typeof Schema.Number; message: typeof Schema.String; detail: Schema.optional; }>; /** HTTP method a function answers on. */ export declare type ServerlessMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; /** * The PLATFORM SHAPE of a serverless target — the half that is pure + runtime- * agnostic, so it lives in `@voltro/serverless` and is unit-testable without any * node/CLI machinery. `entryModule` produces the platform's entrypoint SOURCE: * it imports the user's `defineServerless` default export from `defImport` and * wraps it with the framework's `serverlessWebHandler` into whatever the host * expects (a Workers `export default { fetch }`, a Scaleway `handle(event)`). * `esbuild` is the recipe to bundle that entry for the host's runtime. */ export declare interface ServerlessPlatform { /** `'cloudflare'` | `'scaleway'` | … */ readonly id: string; /** Human label for logs. */ readonly label: string; /** The platform entrypoint source. `defImport` is the import specifier the * generated entry uses to load the user's function (an absolute path). */ readonly entryModule: (defImport: string) => string; readonly esbuild: EsbuildHints; } /** Platform deploy hints — best-effort; a host ignores what it can't honour. */ export declare interface ServerlessRuntimeHints { readonly memoryMb?: number; readonly timeoutSeconds?: number; /** Provider region (e.g. `fr-par` for Scaleway). Cloudflare is global. */ readonly region?: string; /** Warm/cap instance counts (provider best-effort). */ readonly minScale?: number; readonly maxScale?: number; } /** * A full deploy target = the platform shape PLUS a `deploy` that ships a bundled * function. `deploy` lives CLI-side (it shells out to the host's official tool — * `wrangler` / `scw` — behind a mockable runner) and is composed onto a * `ServerlessPlatform` there; the framework never reimplements a host's upload * wire protocol. */ export declare interface ServerlessTarget extends ServerlessPlatform { /** Ship the bundle. `config` is the resolved per-target deploy config * (tokens, account ids, region) — providers validate what they need. */ readonly deploy: (fn: BuiltFunction, config: ServerlessDeployConfig) => Effect.Effect; } /** * Build the Web handler for a single serverless definition. The returned * function is a standard `(Request) => Promise` runnable on any * fetch-based runtime; the platform adapters wrap it. */ export declare const serverlessWebHandler: (def: ServerlessDefinition, options?: WebHandlerOptions) => ((request: Request) => Promise); export declare interface StaticDeployConfig { readonly env: Record; /** Per-host options (bucket, account id, project name, region, …). */ readonly options?: Record; /** SPA fallback: serve `index.html` for unknown routes (off for pure SSG with * per-route `dist//index.html`, on for a single-page app). */ readonly spaFallback?: boolean; readonly dryRun?: boolean; } export declare class StaticDeployError extends StaticDeployError_base { } declare const StaticDeployError_base: Schema.TaggedErrorClass; } & { host: typeof Schema.String; message: typeof Schema.String; detail: Schema.optional; }>; export declare interface StaticDeployResult { readonly host: string; /** Public URL of the deployment, when the provider returns one. */ readonly url?: string; readonly filesUploaded: number; /** Files skipped because the host already had identical bytes (diff upload). */ readonly filesSkipped: number; } /** A static-hosting provider — ships a built `dist/` directory. */ export declare interface StaticHost { /** `'cloudflare-pages'` | `'scaleway-object-storage'` | `'s3'` | `'netlify'` */ readonly id: string; readonly label: string; readonly deploy: (distDir: string, config: StaticDeployConfig) => Effect.Effect; } export declare interface WebHandlerOptions { /** Env / secrets exposed to the handler via `ctx.env`. */ readonly env?: Record; /** Background-work scheduler (Cloudflare `ctx.waitUntil`); default no-op. */ readonly waitUntil?: (promise: Promise) => void; } export { }