1import type { InputProps } from "../../Input.ts";
2import * as Namespace from "../../Namespace.ts";
3import { makeFrameworkSite, type FrameworkSiteProps } from "./FrameworkSite.ts";
4
5/** The framework-integration package that drives the Waku build. */
6export const WAKU_FRAMEWORK_SPECIFIER = "@alchemy.run/frontend-frameworks/waku";
7
8/** The AWS Lambda deploy target for the Waku build. */
9export const WAKU_AWS_TARGET_SPECIFIER =
10 "@alchemy.run/frontend-frameworks/waku/aws";
11
12export interface WakuProps extends FrameworkSiteProps {
13 /**
14 * Waku config overrides merged over the project's `waku.config.*`
15 * (per-key; deploy-time values win). For values that vary by stage or
16 * come from other resources — static config belongs in `waku.config.*`.
17 */
18 waku?: {
19 /**
20 * Waku `srcDir` (relative to {@link FrameworkSiteProps.rootDir}).
21 * @default "src"
22 */
23 srcDir?: string;
24 /**
25 * Waku `distDir` (relative to {@link FrameworkSiteProps.rootDir}).
26 * A custom `distDir` must be gitignored (or added to `memo.exclude`)
27 * so the build output stays excluded from the rebuild-deciding input
28 * hash.
29 * @default "dist"
30 */
31 distDir?: string;
32 /**
33 * Waku `basePath`.
34 * @default "/"
35 */
36 basePath?: string;
37 };
38}
39
40/**
41 * Deploy a [Waku](https://waku.gg) application to AWS: the RSC server on a
42 * streaming Lambda Function URL, static assets (SSG pages included) in S3,
43 * and a CloudFront distribution whose edge router serves uploaded files
44 * from S3 and forwards everything else to the server.
45 *
46 * The build runs through `@alchemy.run/frontend-frameworks/waku` with the
47 * `@alchemy.run/frontend-frameworks/waku/aws` deploy target (this package's fork
48 * of waku's aws-lambda adapter, streaming enabled) — both must be installed
49 * in your project.
50 *
51 * ### Creating Waku Sites
52 * **Example:** Basic Waku App
53 * ```typescript
54 * const site = yield* AWS.Website.Waku("Web", {
55 * rootDir: "./app",
56 * });
57 * ```
58 *
59 * **Example:** Custom Domain
60 * ```typescript
61 * const site = yield* AWS.Website.Waku("Web", {
62 * rootDir: "./app",
63 * domain: {
64 * name: "app.example.com",
65 * hostedZoneId: zone.hostedZoneId,
66 * },
67 * });
68 * ```
69 *
70 * ### Server Configuration
71 * **Example:** Tune The Server Function
72 * ```typescript
73 * const site = yield* AWS.Website.Waku("Web", {
74 * rootDir: "./app",
75 * memorySize: 2048,
76 * env: {
77 * API_BASE: api.url,
78 * },
79 * });
80 * ```
81 *
82 * ### Waku Config Overrides
83 * Waku configuration lives in your `waku.config.*`. The `waku` prop
84 * overrides it per key at deploy time — for values that vary by stage
85 * or come from other resources.
86 *
87 * **Example:** Stage-dependent base path
88 * ```typescript
89 * const site = yield* AWS.Website.Waku("Web", {
90 * waku: {
91 * basePath: "/docs/",
92 * },
93 * });
94 * ```
95 *
96 * @resource
97 */
98export const Waku = (id: string, props: InputProps<WakuProps> = {}) => {
99 const p = props as WakuProps;
100 return makeFrameworkSite(id, props, {
101 name: "Waku",
102 framework: WAKU_FRAMEWORK_SPECIFIER,
103 target: WAKU_AWS_TARGET_SPECIFIER,
104 // Deploy-time waku config overrides, merged over the project's
105 // `waku.config.*` by the integration (per-key; overrides win).
106 options: p.waku !== undefined ? { waku: p.waku } : undefined,
107 }).pipe(Namespace.push(id));
108};