import * as Effect from "effect/Effect"; import type { MemoOptions } from "../../Command/Memo.ts"; import type { InputProps } from "../../Input.ts"; import type { Providers } from "../Providers.ts"; import type { AssetsConfig } from "../Workers/Assets.ts"; import { Worker, type NormalizedBindings, type WorkerAssetsConfig, type WorkerBindingProps, type WorkerProps } from "../Workers/Worker.ts"; export interface WakuProps extends Omit, "vite" | "main" | "assets" | "source" | "script" | "bundle"> { /** * Overrides the module that becomes the deployed Worker entry. Relative * paths resolve from {@link rootDir}. * * By default Waku's own RSC server entry is deployed. Point `main` at a * custom module when the deployed Worker must export more than Waku's * fetch handler — e.g. Durable Object classes or additional handlers. * The custom entry wraps Waku's handler by importing it from * `virtual:waku/server-entry` and re-exports the extras: * * ```typescript * // src/worker-entry.ts * import wakuHandler from "virtual:waku/server-entry"; * export class Counter extends DurableObject {} * export default { * fetch: (request, env, ctx) => wakuHandler.fetch(request, env, ctx), * }; * ``` */ main?: string; /** * Root directory of the Waku project. Defaults to the process working * directory. */ rootDir?: string; /** * Waku source directory, relative to {@link rootDir}. Setting this * overrides a `srcDir` in the project's `waku.config.*`. * @default the project's `waku.config.*` value, or waku's own default (`"src"`) */ srcDir?: string; /** * Waku build output directory, relative to {@link rootDir}. The server * bundle is read from `/server` and the client assets from * `/public`. Setting this overrides a `distDir` in the * project's `waku.config.*` — if your config file customizes `distDir`, * mirror it here (or exclude it via `memo`) so the build output doesn't * pollute the rebuild hash. * @default the project's `waku.config.*` value, or waku's own default (`"dist"`) */ distDir?: string; /** * Base path the app is served under. Setting this overrides a * `basePath` in the project's `waku.config.*`. * @default the project's `waku.config.*` value, or waku's own default (`"/"`) */ basePath?: string; /** * Controls which files feed the content hash that decides whether a * rebuild is needed. By default every non-gitignored file under * {@link rootDir} is hashed, plus the nearest package-manager lockfile. * Provide `include`/`exclude` globs to narrow the scope. */ memo?: MemoOptions; /** * Optional configuration for static asset routing behavior. * Supports `runWorkerFirst`, `htmlHandling`, `notFoundHandling`, etc. * * Waku links SSG pages without trailing slashes (`/about`), so * `htmlHandling` defaults to `"drop-trailing-slash"` — the prerendered * `about/index.html` serves directly at `/about` instead of 307-redirecting * to `/about/`. Set `htmlHandling` explicitly to override. * * @default { htmlHandling: "drop-trailing-slash" } */ assets?: AssetsConfig; } /** * A Cloudflare Worker deployed from a [Waku](https://waku.gg) project. * * `Waku` builds the project programmatically — no `waku.config.ts` edits, * no Wrangler configuration, and no build command required. A project's * `waku.config.*` loads natively (same as waku's CLI) as the base config, * with `srcDir`/`distDir`/`basePath` from this resource winning per key; * `unstable_adapter` is owned by Alchemy and must not be set. Note that a * standalone `vite.config.ts` is NOT loaded (same as waku's CLI) — Vite * config belongs in `waku.config.*`'s `vite` field. The RSC server * bundle deploys as the Worker script and the client output (including * SSG-prerendered pages) deploys as static assets. * * Requires the `@alchemy.run/frontend-frameworks` package to be installed in * your project; the integration is loaded from its `/waku` export. Input files * are content-hashed * (respecting `.gitignore` by default) so unchanged projects skip the * build and deploy entirely. * * Waku's server runtime uses `AsyncLocalStorage`, so the `nodejs_als` * compatibility flag is enabled automatically when your compatibility * flags include neither `nodejs_als` nor `nodejs_compat`. SSG pages are * served at their extensionless URLs (`/about`) via the default * `drop-trailing-slash` asset handling. * * * ### Deploying a Waku Site * A single call builds the project and deploys the RSC server bundle plus * the client assets — no configuration required. * * **Example:** Waku site * ```typescript * const site = yield* Cloudflare.Website.Waku("Site"); * ``` * * **Example:** Waku project in a subdirectory * ```typescript * const site = yield* Cloudflare.Website.Waku("Site", { * rootDir: "apps/web", * }); * ``` * * ### Bindings * Pass resources through `env` like any other Worker. Server components * and API routes read them from the `cloudflare:workers` env at request * time. Prefer a guarded dynamic import in page modules — Waku's SSG step * renders static pages in Node, where a top-level * `import { env } from "cloudflare:workers"` cannot resolve. * * **Example:** Binding an R2 bucket * ```typescript * const bucket = yield* Cloudflare.R2.Bucket("Uploads"); * * const site = yield* Cloudflare.Website.Waku("Site", { * env: { * UPLOADS: bucket, * }, * }); * ``` * * ### Custom Worker Entry * By default the deployed Worker entry is Waku's own RSC server entry. * When the Worker must export more than Waku's fetch handler — Durable * Object classes, additional handlers — point `main` at your own module * that wraps Waku's handler (imported from `virtual:waku/server-entry`) * and re-exports the extras. * * **Example:** Custom entry hosting a Durable Object * ```typescript * // src/worker-entry.ts * // import wakuHandler from "virtual:waku/server-entry"; * // export class Counter extends DurableObject { ... } * // export default { fetch: (req, env, ctx) => wakuHandler.fetch(req, env, ctx) }; * * const site = yield* Cloudflare.Website.Waku("Site", { * main: "src/worker-entry.ts", * env: { * COUNTER: Cloudflare.DurableObject("Counter", { * className: "Counter", * }), * }, * }); * ``` * * ### Custom Rebuild Scope * By default, every non-gitignored file is hashed to decide whether a * rebuild is needed. Use `memo` to narrow the scope when your project has * large directories that don't affect the build output. * * **Example:** Narrowing the memo scope * ```typescript * const site = yield* Cloudflare.Website.Waku("Site", { * memo: { * include: ["src/**", "public/**", "package.json"], * }, * }); * ``` * * ### Class Form * Calling `Waku` with no arguments returns a constructor you can `extend` * to declare the Worker as a named class. The class is both an `Effect` * you can `yield*` to deploy and a type you can reference elsewhere — * useful when other resources need to bind to this Worker. * * **Example:** Declaring a Waku Worker class * ```typescript * class Site extends Cloudflare.Website.Waku()("Site") {} * * const site = yield* Site; * ``` * * @resource * @product Website * @category Workers & Compute */ export declare const Waku: { (): { (id: string, propsEff?: InputProps> | Effect.Effect>, never, Req>): Effect.Effect & { new (): Worker<{ [binding in keyof NormalizedBindings]: NormalizedBindings[binding]; }>; }; }; (id: string, propsEff?: InputProps> | Effect.Effect>, never, Req>): Effect.Effect]: NormalizedBindings[binding]; }>, never, Req | Providers>; }; //# sourceMappingURL=Waku.d.ts.map