1import {
2 DurableObjectNamespace,
3 KvNamespace,
4 Text,
5} from "@alchemy.run/cloudflare-runtime/core/bindings";
6import * as Options from "@alchemy.run/cloudflare-test-tools/e2e/Options";
7import * as Nuxt from "@alchemy.run/frontend-frameworks/nuxt";
8
9const SECRET = "s3cret-from-binding";
10
11/**
12 * A Nuxt 4 app built through nitro's `cloudflare_module` preset
13 * (wrangler-free), with the user's own Durable Object hosted on the SAME
14 * worker via the nitro entry/exports seam (`main: "./worker-entry.ts"`).
15 */
16export default Options.make({
17 // The typed factory form (harness contract form 3): map the harness
18 // options onto Nuxt options, then pin the dev port so parallel fixture
19 // runs don't collide. `framework: "@alchemy.run/frontend-frameworks/nuxt"` (the string
20 // form) works identically when no framework-specific options are needed.
21 // The deploy target defaults to `@alchemy.run/frontend-frameworks/nuxt/cloudflare`.
22 framework: (options) => {
23 const base = Nuxt.fromHarnessOptions(options as Nuxt.HarnessOptions);
24 return Nuxt.layer({
25 ...base,
26 dev: {
27 ...base.dev,
28 port: 3111,
29 // Dev serves an explicit binding set instead of the worker's
30 // declared hooks: the dev platform proxy cannot host the Counter DO
31 // class (the entry/exports seam only exists in the production
32 // build), so the DO spec is live-only while Text + KV round-trip
33 // through the proxy.
34 bindings: [
35 Text.local("FIXTURE_SECRET", SECRET),
36 KvNamespace.local({ binding: "FIXTURE_KV" }),
37 ],
38 },
39 });
40 },
41 target: {
42 cloudflare: {
43 worker: {
44 compatibilityDate: "2026-03-10",
45 compatibilityFlags: ["nodejs_compat"],
46 // The user-entry seam: nitro bundles this module as the worker
47 // entry; it wraps nitro's handler and exports the Counter DO class.
48 main: "./worker-entry.ts",
49 worker: {
50 name: "fixtures-nuxt",
51 bindings: [
52 Text.local("FIXTURE_SECRET", SECRET),
53 KvNamespace.local({ binding: "FIXTURE_KV" }),
54 // Bind the namespace for a DO class exported by THIS worker.
55 DurableObjectNamespace.local({
56 binding: "COUNTER",
57 className: "Counter",
58 }),
59 ],
60 // The dev runtime's DO declaration (workerd durableObjectNamespaces).
61 durableObjectNamespaces: [{ className: "Counter", sql: true }],
62 assets: {
63 htmlHandling: "auto-trailing-slash",
64 notFoundHandling: "none",
65 },
66 },
67 },
68 preview: {
69 compatibilityDate: "2026-03-10",
70 compatibilityFlags: ["nodejs_compat"],
71 bindings: { FIXTURE_SECRET: SECRET },
72 kvNamespaces: ["FIXTURE_KV"],
73 // Miniflare's DO declaration for the preview server: binding name ->
74 // class exported by the built worker bundle.
75 durableObjects: { COUNTER: { className: "Counter", useSQLite: true } },
76 assets: {
77 binding: "ASSETS",
78 routerConfig: {
79 has_user_worker: true,
80 invoke_user_worker_ahead_of_assets: false,
81 },
82 assetConfig: {
83 html_handling: "auto-trailing-slash",
84 not_found_handling: "none",
85 },
86 },
87 },
88 },
89 },
90});