1/**
2 * `@alchemy.run/frontend-frameworks/sveltekit` — SvelteKit integration implementing
3 * framework-core's `Framework` service, with the deploy target passed as a
4 * value (Cloudflare Workers by default, via the
5 * `@alchemy.run/frontend-frameworks/sveltekit/cloudflare` subpath module).
6 *
7 * The default export is the e2e-harness factory contract: a
8 * `(options) => Layer<Framework>` function that reads the harness's
9 * cloudflare-target configuration (compatibility date/flags, worker bindings,
10 * assets behavior). Use {@link layer} directly for the fully-typed path with
11 * SvelteKit-specific options.
12 *
13 * This module (and `SvelteKit.ts`) is target-agnostic by contract: it must
14 * not import anything Cloudflare-specific. The Cloudflare half — the
15 * in-memory kit adapter fork, the workerd rolldown finishing pass, the
16 * proxy-backed dev platform — lives behind
17 * `@alchemy.run/frontend-frameworks/sveltekit/cloudflare`.
18 */
19import type { Framework } from "../core/index.ts";
20import type * as FileSystem from "effect/FileSystem";
21import type * as Layer from "effect/Layer";
22import type * as Path from "effect/Path";
23import { layer, type SvelteKitOptions } from "./SvelteKit.ts";
24
25export {
26 DEFAULT_TARGET_SPECIFIER,
27 layer,
28 make,
29 resolveExportTarget,
30 type SvelteKitAdapter,
31 type SvelteKitAdapterContext,
32 type SvelteKitAdapterOptions,
33 type SvelteKitAdapterResult,
34 type SvelteKitOptions,
35 type SvelteKitTarget,
36 type SvelteKitTargetConfig,
37 type SvelteKitTargetInput,
38} from "./SvelteKit.ts";
39
40export {
41 CONFIG_PLUGIN_NAME,
42 DEFAULT_VITE_CONFIG_FILES,
43 flattenPluginOption,
44 makeSvelteKitConfigPlugin,
45 mergeKitOptions,
46 SVELTEKIT_SETUP_PLUGIN_NAME,
47 type SvelteKitConfigPluginOptions,
48} from "./UserConfig.ts";
49
50/**
51 * The structural subset of the e2e harness's cloudflare worker options this
52 * package reads (`CloudflareVitePluginOptions`). Typed structurally so the
53 * package does not depend on the harness.
54 */
55export interface HarnessWorkerOptions {
56 readonly compatibilityDate?: string | undefined;
57 readonly compatibilityFlags?: Array<string> | undefined;
58 readonly worker?:
59 | {
60 readonly bindings?: ReadonlyArray<unknown> | undefined;
61 readonly assets?:
62 | {
63 readonly notFoundHandling?:
64 | "none"
65 | "404-page"
66 | "single-page-application"
67 | undefined;
68 }
69 | undefined;
70 }
71 | undefined;
72}
73
74/**
75 * The structural subset of the e2e harness's `Options` this package reads.
76 * The harness carries cloudflare configuration target-scoped
77 * (`target.cloudflare.worker`); the top-level `vite` field is the harness's
78 * deprecated alias for the same shape (target-scoped wins).
79 */
80export interface HarnessOptions {
81 readonly target?:
82 | {
83 readonly cloudflare?:
84 | {
85 readonly worker?: HarnessWorkerOptions | undefined;
86 }
87 | undefined;
88 }
89 | undefined;
90 /** @deprecated Harness alias for `target.cloudflare.worker`. */
91 readonly vite?: HarnessWorkerOptions | undefined;
92}
93
94/**
95 * Map the harness's options onto {@link SvelteKitOptions}, preferring the
96 * target-scoped carriage (`target.cloudflare.worker`) over the deprecated
97 * top-level `vite` alias. The worker's declared binding hooks are passed
98 * through to the deploy target's dev platform wholesale (the Cloudflare
99 * target serves them on `platform.env` via cloudflare-runtime's platform
100 * proxy — resource bindings included, not just literal values).
101 */
102export const fromHarnessOptions = (
103 options: HarnessOptions,
104): SvelteKitOptions => {
105 const worker = options.target?.cloudflare?.worker ?? options.vite;
106 return {
107 compatibilityDate: worker?.compatibilityDate,
108 compatibilityFlags: worker?.compatibilityFlags,
109 adapter: {
110 notFoundHandling: worker?.worker?.assets?.notFoundHandling,
111 },
112 dev: {
113 bindings: worker?.worker?.bindings,
114 },
115 };
116};
117
118/**
119 * The e2e-harness factory contract (`framework: "@alchemy.run/frontend-frameworks/sveltekit"`
120 * in `e2e.config.ts`).
121 */
122const factory = (
123 options: HarnessOptions,
124): Layer.Layer<Framework, never, FileSystem.FileSystem | Path.Path> =>
125 layer(fromHarnessOptions(options));
126
127export default factory;