| 1 | import type * as Redacted from "effect/Redacted"; |
| 2 | import type { BundleConfig } from "../Bundle/Bundle.ts"; |
| 3 | import { Platform, type Main, type PlatformProps } from "../Platform.ts"; |
| 4 | import type { Resource } from "../Resource.ts"; |
| 5 | import type { BranchScope } from "./BranchScope.ts"; |
| 6 | import type { |
| 7 | FunctionEnvironment, |
| 8 | FunctionRequest, |
| 9 | } from "./FunctionEnvironment.ts"; |
| 10 | import { |
| 11 | makeFunctionRuntimeContext, |
| 12 | type FunctionRuntimeContext, |
| 13 | } from "./FunctionRuntimeContext.ts"; |
| 14 | import type { Providers } from "./Providers.ts"; |
| 15 | |
| 16 | /** |
| 17 | * Prebuilt Node 24 Fetch application. The directory or ZIP must contain |
| 18 | * `index.mjs` at its root, exporting a Fetch handler or an object with `fetch`. |
| 19 | * Include all runtime dependencies; Alchemy does not bundle prebuilt artifacts. |
| 20 | * Archives must not contain symlinks, traversal paths, or deployment secrets. |
| 21 | */ |
| 22 | export type FunctionArtifact = |
| 23 | | { |
| 24 | /** Directory packaged into a deterministic ZIP. */ directory: string; |
| 25 | zip?: never; |
| 26 | } |
| 27 | | { /** Path to an existing ZIP archive. */ zip: string; directory?: never }; |
| 28 | |
| 29 | export interface FunctionCommonProps extends PlatformProps { |
| 30 | /** Immutable lowercase alphanumeric identifier, at most 20 characters. Generated when omitted. */ |
| 31 | slug?: string; |
| 32 | /** Mutable display name. Removing it restores the slug. */ |
| 33 | name?: string; |
| 34 | /** Write-only values. Removing a managed key sends an empty deletion value. Platform-injected keys cannot be overridden. */ |
| 35 | env?: Record<string, string | Redacted.Redacted<string> | undefined>; |
| 36 | /** Node-targeted bundler options; not used with prebuilt artifacts. */ |
| 37 | bundle?: BundleConfig; |
| 38 | /** Local Neon CLI executable (version 2.45.0 or newer) and optional listening port. */ |
| 39 | dev?: { command?: string; port?: number }; |
| 40 | } |
| 41 | |
| 42 | export type FunctionProps = BranchScope & |
| 43 | FunctionCommonProps & |
| 44 | ( |
| 45 | | { |
| 46 | /** Native Fetch or Effect entry module. */ main: string; |
| 47 | artifact?: never; |
| 48 | } |
| 49 | | { |
| 50 | /** Prebuilt Fetch application, mutually exclusive with main. */ artifact: FunctionArtifact; |
| 51 | main?: never; |
| 52 | } |
| 53 | ); |
| 54 | |
| 55 | export interface FunctionAttributes { |
| 56 | /** Owning project. */ projectId: string; |
| 57 | /** Owning branch. */ branchId: string; |
| 58 | /** Stable function ID. */ functionId: string; |
| 59 | /** Immutable invocation slug. */ slug: string; |
| 60 | /** Observed display name. */ name: string; |
| 61 | /** Public invocation URL. Authenticate callers in the handler. */ url: string; |
| 62 | /** Latest deployment identifier. */ currentDeploymentId: number | undefined; |
| 63 | /** Deployment currently serving traffic. */ activeDeploymentId: |
| 64 | | number |
| 65 | | undefined; |
| 66 | /** Latest deployment build status. */ status: string | undefined; |
| 67 | /** Digest of the last successfully applied artifact, not a remote code attestation. */ codeHash: |
| 68 | | string |
| 69 | | undefined; |
| 70 | /** Last applied environment digest, not proof of remote write-only value equality. */ environmentHash?: string; |
| 71 | /** Previously managed environment names. Values cannot be read back. */ environment: string[]; |
| 72 | } |
| 73 | |
| 74 | export interface FunctionBinding { |
| 75 | /** Namespaced application configuration; conflicts with user values are rejected. */ |
| 76 | env?: Record<string, string | Redacted.Redacted<string> | undefined>; |
| 77 | } |
| 78 | |
| 79 | export interface Function extends Resource< |
| 80 | "Neon.Function", |
| 81 | FunctionProps, |
| 82 | FunctionAttributes, |
| 83 | FunctionBinding, |
| 84 | Providers |
| 85 | > {} |
| 86 | |
| 87 | /** |
| 88 | * Node.js 24 Fetch function, with native and Effect entrypoints. |
| 89 | * |
| 90 | * Functions have public URLs. The `functions:invoke` credential scope does not |
| 91 | * establish a private invocation policy. Authenticate requests in your handler. |
| 92 | * Native same-branch database/storage credentials are injected by Neon; a typed |
| 93 | * read-only binding does not restrict the credentials available to the process. |
| 94 | * Explicit adoption takes ownership of user-defined environment names: existing |
| 95 | * keys omitted from `env` and bindings are removed. Values are write-only, so |
| 96 | * cached digests cannot detect out-of-band value drift. |
| 97 | * |
| 98 | * ### Streaming disconnects <!-- api-prose --> |
| 99 | * |
| 100 | * Neon’s production host currently does not reliably propagate client disconnects |
| 101 | * to uncompressed response streams. An abandoned stream can retain its producer |
| 102 | * and request-scoped resources until it finishes. Prefer finite responses and |
| 103 | * application-bounded streams; do not rely on disconnect cleanup for long-lived |
| 104 | * streaming workloads until [the upstream issue](https://github.com/neondatabase/neon-pkgs/issues/636) |
| 105 | * is resolved. Alchemy propagates abort and body-cancel signals when the host supplies them. |
| 106 | * |
| 107 | * ### Native Fetch |
| 108 | * **Example:** Bundle a native object, bare handler, or Hono application |
| 109 | * ```typescript |
| 110 | * const api = yield* Neon.Function("Api", { branch, main: "./src/api.ts" }); |
| 111 | * ``` |
| 112 | * |
| 113 | * ### Effect Fetch |
| 114 | * **Example:** Class entrypoint |
| 115 | * ```typescript |
| 116 | * export default class Api extends Neon.Function<Api>()( |
| 117 | * "Api", { branch, main: import.meta.url }, |
| 118 | * Effect.succeed({ fetch: Effect.succeed(HttpServerResponse.text("ok")) }), |
| 119 | * ) {} |
| 120 | * ``` |
| 121 | * |
| 122 | * ### Prebuilt Applications |
| 123 | * **Example:** Deploy Website build output without rebundling |
| 124 | * ```typescript |
| 125 | * const site = yield* Neon.Function("Site", { branch, artifact: { directory: "./dist" } }); |
| 126 | * ``` |
| 127 | * |
| 128 | * @resource |
| 129 | * @product Function |
| 130 | */ |
| 131 | export const Function: Platform< |
| 132 | Function, |
| 133 | FunctionEnvironment, |
| 134 | Main<FunctionEnvironment | FunctionRequest>, |
| 135 | FunctionRuntimeContext |
| 136 | > = Platform<Function>("Neon.Function", { |
| 137 | createRuntimeContext: makeFunctionRuntimeContext, |
| 138 | }); |