1/**
2 * The git-service example: a git host embedded in the app's own API, plus
3 * a GitHub-style web UI, on one origin.
4 *
5 * - `src/api/` — the backend, one file per piece: `auth.ts` (Better Auth
6 * and who a user is), `middleware.ts` (who may call what), `routes.ts`
7 * (the app's own routes), `api.ts` (the git routes plus ours behind the
8 * middleware), `git.ts` (the `alchemy/Git` block assembly), and
9 * `host.ts` (the `Cloudflare.Worker` that serves it).
10 * - `src/ui/` — the Vite SPA, a plain-fetch client of the API.
11 * - `src/worker.ts` — the website's Worker: forwards `/api/**` and the git
12 * wire paths to the GitHost over a service binding and serves the SPA for
13 * everything else, so clone URLs and the session cookie are same-host.
14 *
15 * ```sh
16 * bun run deploy
17 * ```
18 *
19 * Open the printed `webUrl`, sign up, mint an API key on the settings page,
20 * and it is the password of your git remote:
21 *
22 * ```sh
23 * git remote add origin "https://x:<key>@<host>/<you>/web.git"
24 * git push origin main
25 * ```
26 */
27import * as Alchemy from "alchemy";
28import * as Cloudflare from "alchemy/Cloudflare";
29import * as Effect from "effect/Effect";
30import GitHost from "./src/api/host.ts";
31
32export default Alchemy.Stack(
33 "GitServiceExample",
34 { providers: Cloudflare.providers(), state: Alchemy.localState() },
35 Effect.gen(function* () {
36 const git = yield* GitHost;
37
38 const web = yield* Cloudflare.Website.Vite("Web", {
39 main: "src/worker.ts",
40 assets: {
41 notFoundHandling: "single-page-application",
42 runWorkerFirst: true,
43 },
44 env: {
45 GIT: GitHost,
46 },
47 });
48
49 return { url: git.url.as<string>(), webUrl: web.url };
50 }),
51);