feat: framework integrations (Astro, SvelteKit, Waku) without wrangler#74
Open
john-royal wants to merge 37 commits into
Open
feat: framework integrations (Astro, SvelteKit, Waku) without wrangler#74john-royal wants to merge 37 commits into
john-royal wants to merge 37 commits into
Conversation
- Move workers-sdk submodule to upstream/workers-sdk - Add shallow submodules: upstream/next.js, upstream/opennextjs-cloudflare, upstream/astro, upstream/sveltekit, upstream/waku - Update path references in docs, lint/format configs, and code comments Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Research specs for Next.js, @opennextjs/cloudflare, Astro, SvelteKit, Waku (programmatic dev/build hooks, Cloudflare integration, wrangler coupling, adaptation plans), internal context maps for cloudflare-tools and alchemy's Website surface, and the synthesized phased implementation plan (PLAN.md). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, SvelteKit, Astro All four spikes proved-with-caveats: - Next: OpenNext programmatic build (2-field config stub) + esbuild final pass + boot in cloudflare-runtime, 11/11 HTTP checks; same-script SQLite DOs / self service binding / ASSETS all work today - Waku: input-merge risk disproven; plugin must ride waku's config.vite.plugins (or fix dev middleware ordering); collector needs post-buildApp disk re-read - SvelteKit: in-memory adapter + zero-config rolldown re-bundle, 9/9 boot checks - Astro: our-plugin-inside-astro validated; needs env scoping + optionsPlugin buildApp guard in our plugins Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…/format Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…dering - skipEnvironments option: applyToEnvironment on per-env plugins, configEnvironment gating, nodejs-compat tolerant of no-discovery optimizers (unblocks Astro's node-side astro/prerender envs) - optionsPlugin only defaults builder.buildApp when the user config doesn't define one (Astro owns its own orchestrator) - dev.middlewareOrder "pre" hoists the workerd proxy ahead of framework post-middlewares via an enforce:pre boundary plugin (unblocks Waku append-last composition); default remains "post" - dev-environment degrades gracefully when configureServer is stripped (Astro typegen temp servers); HotChannel close hardening Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Service.self(name): same-script self service binding
(WORKER_SELF_REFERENCE); bypasses the assets middleware chain
- RuntimeWorker.logging { verbose, onOutput }: surface workerd's
exception output instead of invisible bare 500s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s, Framework service New package @distilled.cloud/framework-core: BuildOutput types + dist/build.json persistence, collector plugin (skipEnvironments, deterministic entry selection, post-buildApp disk re-read), project module loaders, and the effectful Framework service contract. tools/e2e refactored onto it with no behavior change (fixture e2e suites verified identical). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
e2e.config.ts gains an optional framework field (package specifier, factory, or Layer) resolved from the fixture's node_modules; dev/build/ preview dispatch through the framework-core Framework service, with the built-in Vite implementation as the default. Contract documented in README.md. Also fixes an ESM cycle (Cwd extracted from Runtime). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
getPlatformProxy equivalent (maintainer policy: reimplemented here, never a wrangler dependency): PlatformProxy.open (Effect) + getPlatformProxy (Promise) return Node-side env/cf/ctx/caches proxies over an internal proxy worker; caches actually round-trip. Plus KvNamespace.local, an in-memory KV plugin. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Framework-service Layer over waku's programmatic vite APIs with a wrangler-free cloudflare adapter fork; cloudflareVitePlugin injected inside wakuConfig.vite.plugins; SSG via __WAKU_START_PREVIEW_SERVER__. Fixture: SSR RSC + binding, SSG, hydration, static assets — 10/10 e2e. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Forked createIntegration running our vite plugin inside astro's build()/dev() (skipEnvironments for astro/prerender envs); vendored runtime entrypoints + virtual-config plugin so neither wrangler nor @cloudflare/vite-plugin enter the tree. Node prerendering, passthrough image service. Fixture: SSR + binding, prerender, 404-via-ASSETS, hydration — 10/10 e2e. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
In-memory kit adapter (generated shim with real import paths, no wrangler config) + post-adapt rolldown pass via cloudflare-rolldown-plugin producing workerd-ready entry-first modules. Dev v1: kit Node SSR with a documented stub platform (real bindings arrive with the platform proxy). Fixture: SSR platform.env, endpoint, prerender, hydration — 10/10 e2e. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
OpenNext build via child-process deep import with a 2-field in-memory config and an inert wrangler stub (no wrangler code ever executes); esbuild finishing pass (workerd conditions, lazy handler chunk, createRequire banner, wasm/bin module rules); static-assets populateCache; dev v1 = preview parity via Runtime.start with Service.self + same-script SQLite DOs. Fixture: SSR, API+middleware, ISR serve, assets, hydration — 16/16 e2e. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
|
Install the packages built from this commit: @distilled.cloud/cloudflare-rolldown-plugin bun add https://pkg.distilled.cloud/cloudflare-rolldown-plugin/3280c29@distilled.cloud/cloudflare-runtime bun add https://pkg.distilled.cloud/cloudflare-runtime/3280c29@distilled.cloud/cloudflare-vite-plugin bun add https://pkg.distilled.cloud/cloudflare-vite-plugin/3280c29 |
Each package exports './source': a structural implementation of alchemy's WorkerSourceModule contract wrapping its Framework service — build() (entry-first bundle + asset manifest + version-salted input hash), hash() (rebuild-free), dev() (server-mode handle). No alchemy imports; errors raise a structural twin of Cloudflare.Workers.SourceProviderError. Also promotes waku's cloudflare-runtime dep out of devDependencies (build-order + publish correctness). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Module names in a BuildOutput become workerd module names and worker upload paths, so they must be /-separated regardless of platform. NodePath.join/relative produce backslashes on Windows, which failed 8 Collector tests (and would have produced invalid worker uploads). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…detection Vite module ids are POSIX even on Windows; comparing them against a backslashed resolved root spuriously classified in-root modules as external workspaces. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Windows keeps workerd's file locks alive briefly after shutdown; retry the scoped temp-directory removal and prefer leaking it over failing dispose. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Windows CI runs every fixture's playwright suite concurrently on a 4-core runner; two consecutive runs failed on two different fixtures with unrelated transient errors (dev-server dep-optimizer reload race, chromium launch death). Retries are CI-only; local runs stay strict. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The OpenNext build copies NFT-traced node_modules built from bun-store junctions; the copy leaves them broken on Windows and esbuild fails with 'Access is denied'. Documented in scripts/e2e.mjs; macOS/Linux unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Concurrent workerd/playwright fixture suites exhaust the Windows runner's socket buffer space (WSAENOBUFS on bind); run test tasks with --concurrency=1 there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Windows CI exhausted AFD/ephemeral-port buffers late in the job (bind WSAENOBUFS, ConnectEx ERROR_DUP_NAME inside workerd). Our contributions, now fixed: - LoopbackServer + vite dev module-fallback server: 60s keepAliveTimeout (Node's 5s default closed workerd's pooled connections every idle gap, churning a TIME_WAIT socket per subrequest); finalizers hard-close connections - Port scan: classify bind errors by code — ENOBUFS/EMFILE now fail fast with a typed PortBindFailed instead of probing 7 hosts across the whole port range; search bounded to 128 candidates - WorkerProxy.serveWithRetry: bounded to 8 workerd spawns (a crash under exhaustion was classified address-in-use and respawned unbounded) - get-address: toConnectableHost normalizes 0.0.0.0/:: so a listen-all bind is never handed to workerd as a connect target (invalid on Windows); cross-platform tests Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Runner-level socket exhaustion (WSAENOBUFS) persists from components outside this repo (chromium, miniflare loopback churn) even after the cloudflare-runtime fixes; documented in scripts/e2e.mjs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…json persistence from the Framework contract
Two concurrent change sets:
- nextjs dev v2 groundwork (DevServer.ts): programmatic next({ dev: true }) +
prepare() on a caller-owned http.Server, with cloudflare-runtime's
PlatformProxy planted on OpenNext's
globalThis[Symbol.for("__cloudflare-context__")] contract (env/cf/ctx) and
the vm.runInContext patch for the edge-runtime sandbox — so
getCloudflareContext() works in next dev without
initOpenNextCloudflareForDev and without wrangler. Plus the package README
documenting preview/hmr dev-mode fidelity.
- framework-core contract simplification: Framework.build is in-memory only
(no dist/build.json side effect), readBuildOutput removed from the service;
the e2e harness persists build.json itself, framework packages
(astro/sveltekit/waku/nextjs/vite) updated accordingly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gs, wrangler-free) Wire DevServer into the Framework service as options.dev.mode: "preview" (default, unchanged v1 workerd preview) | "hmr". The source descriptor (NextjsSourceOptions) surfaces the same JSON-stable dev.mode. fixtures/nextjs: hmr-mode dev spec (test/hmr.test.ts) driving the Framework service directly — page serves through next dev, getCloudflareContext().env binding value visible in SSR output and an API route, and a page edit is reflected on a subsequent request (bounded Effect retry, file restored in a finally). playwright build.external excludes .next/** so playwright's babel require-hook doesn't choke on Turbopack's sectioned source maps; scripts/hmr-repro.mjs is a minimal manual runner for the same path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Next.js/OpenNext integration needs more iteration (bundler consolidation, dependency internalization, the coming adapters-api migration) — moved to its own branch + draft PR so the Waku/Astro/ SvelteKit integrations can land independently. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…zation The deploy target (conditions, finishing pass, dev serving, config carriage) becomes a value passed to framework packages; Cloudflare is the first target implementation (harness CloudflareTarget). Groundwork for future AWS targets — framework orchestration stays platform-neutral. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Their durable content now lives in package READMEs and AGENTS.md (architecture, doctrine, per-framework limitations); the rest is git history. Also removes the untracked build-artifact leftovers from the split-out nextjs fixture and prunes the related lint ignores. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
vocs 2.6 is Waku-based; the fixture drives its plugin stack through the refactored @distilled.cloud/waku/cloudflare target hooks with two fixture-local workerd bridges (build-time config resolution; no new Function in config revival). 9/9 playwright (live + dev). Also finishes the spike/research retirement (on-disk artifact removal, lint-ignore pruning). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Framework integrations for Astro, SvelteKit, and Waku with no wrangler dependency and no wrangler config files anywhere. (Next.js is split out to #82.)
Architecture: frameworks × deploy targets
Each framework package (
waku,astro,sveltekit) is split into platform-neutral orchestration and a Cloudflare target module at the./cloudflaresubpath (adapter forks, vite-plugin injection, workerd dev). Framework options taketargetas a prop; per-package import-boundary tests enforce zero cloudflare imports outside the target modules. Future AWS targets slot in as sibling target modules without touching the framework halves — groundwork for AWS website resources.framework-core—BuildOutputcontract, collector, loaders,Frameworkservice,DeployTarget.waku— programmatic vite build/dev, wrangler-free adapter fork, SSG.astro— forkedcreateIntegration; vendored runtime entrypoints (neitherwranglernor@cloudflare/vite-pluginenter the tree).sveltekit— in-memory kit adapter + rolldown finishing pass../sourceentry implementing alchemy'sWorkerSourceModulecontract structurally.Fixtures
Deep per-framework coverage (live + dev playwright): waku — server actions, dynamic routes, API routes, hydration, SSG (20 tests); astro — middleware/locals, redirects, binary endpoints, content collections, islands (18); sveltekit — form actions with and without JS, cookie loads, route groups, binary endpoints, prerender+SSR mix (22); plus vocs (Waku-based docs framework) riding the waku cloudflare target with two documented workerd bridges (9); and the five pre-existing fixtures.
Supporting changes
cloudflare-runtime:PlatformProxy.open/getPlatformProxy(wrangler-free platform proxy),KvNamespace.local,Service.self(), workerd exception capture, Windows socket-churn fixes.cloudflare-vite-plugin/cloudflare-rolldown-plugin:skipEnvironments, guardedbuildAppdefault,dev.middlewareOrder.tools/e2e: pluggable Framework services; target-scoped config carriage (options.target, legacyvite/miniflarealiases kept); harness ownsdist/build.json—Framework.build()is pure.upstream/:workers-sdkmoved underupstream/; shallow submodules for next.js, opennextjs-cloudflare, astro, sveltekit, waku.CI green on ubuntu/macos/windows (fixture e2e serialized on Windows; sveltekit fixture gated there — documented runner-level socket exhaustion).
🤖 Generated with Claude Code