1import { isDeployTarget, type DeployTargetInput } from "../core/index.ts";
2import type { WakuTarget } from "../waku/Waku.ts";
3
4/**
5 * A deploy target capable of hosting Vocs' Waku/RSC runtime.
6 *
7 * Vocs uses Waku's adapter and environment topology, so its target contract
8 * deliberately extends the existing Waku target hooks. The distinct type and
9 * module boundary keep Vocs target selection independent from the Waku
10 * framework integration.
11 */
12export interface VocsTarget<Config = unknown> extends WakuTarget<Config> {}
13
14/** Target-scoped configuration carried by the shared E2E harness. */
15export interface VocsHarnessTargetOptions {
16 readonly name?: string | undefined;
17 readonly cloudflare?: { readonly worker?: unknown } | undefined;
18}
19
20export type VocsTargetOption =
21 | DeployTargetInput<VocsTarget, unknown>
22 | VocsHarnessTargetOptions;
23
24/** The default target is Vocs' own Cloudflare target module. */
25export const DEFAULT_TARGET_SPECIFIER =
26 "@alchemy.run/frontend-frameworks/vocs/cloudflare";
27
28const isDeployTargetInput = (
29 value: unknown,
30): value is DeployTargetInput<VocsTarget, unknown> =>
31 typeof value === "string" ||
32 typeof value === "function" ||
33 isDeployTarget(value);
34
35export interface VocsTargetInputSelection {
36 readonly input: DeployTargetInput<VocsTarget, unknown>;
37 readonly config: unknown;
38}
39
40/** Normalize direct target inputs and the E2E harness's target carriage. */
41export const selectVocsTargetInput = (options?: {
42 readonly target?: VocsTargetOption | undefined;
43 readonly vite?: unknown;
44}): VocsTargetInputSelection => {
45 const raw = options?.target;
46 if (raw !== undefined && isDeployTargetInput(raw)) {
47 return { input: raw, config: options?.vite };
48 }
49 return {
50 input: DEFAULT_TARGET_SPECIFIER,
51 config: raw?.cloudflare?.worker ?? options?.vite,
52 };
53};
54
55export const isVocsTarget = (value: unknown): value is VocsTarget =>
56 isDeployTarget(value) &&
57 typeof (value as { adapter?: unknown }).adapter === "function" &&
58 typeof (value as { vitePlugins?: unknown }).vitePlugins === "function";