1import * as Cloudflare from "alchemy/Cloudflare";
2import * as Effect from "effect/Effect";
3
4export type Metadata = {
5 description: string;
6 topics: string[];
7 stars: number;
8 createdAt: number;
9};
10
11export default class Repo extends Cloudflare.DurableObject<Repo>()(
12 "Repo",
13 Effect.gen(function* () {
14 const state = yield* Cloudflare.DurableObjectState;
15 return Effect.gen(function* () {
16 let meta = (yield* state.storage.get<Metadata>("meta")) ?? null;
17
18 const ensure = Effect.gen(function* () {
19 if (meta === null) {
20 return yield* Effect.fail(new Error("repo not initialized"));
21 }
22 return meta;
23 });
24
25 return {
26 init: (description: string) =>
27 Effect.gen(function* () {
28 if (meta !== null) return meta;
29 meta = {
30 description,
31 topics: [],
32 stars: 0,
33 createdAt: Date.now(),
34 };
35 yield* state.storage.put("meta", meta);
36 return meta;
37 }),
38 get: () => ensure,
39 update: (patch: Partial<Pick<Metadata, "description" | "topics">>) =>
40 Effect.gen(function* () {
41 const current = yield* ensure;
42 meta = { ...current, ...patch };
43 yield* state.storage.put("meta", meta);
44 return meta;
45 }),
46 star: () =>
47 Effect.gen(function* () {
48 const current = yield* ensure;
49 meta = { ...current, stars: current.stars + 1 };
50 yield* state.storage.put("meta", meta);
51 return meta;
52 }),
53 };
54 });
55 }),
56) {}