1import * as Alchemy from "alchemy";
2import { adopt } from "alchemy/AdoptPolicy";
3import * as Cloudflare from "@alchemy.run/cloudflare";
4import { retain } from "alchemy/RemovalPolicy";
5import * as Effect from "effect/Effect";
6import * as NodeURL from "node:url";
7
8const protocol = new URL("../vendor/vite-plus-remote-cache-cloudflare/", import.meta.url);
9
10export const cacheName = Effect.gen(function* () {
11 const { stage } = yield* Alchemy.Stack;
12 return stage === "prod" ? "t3-task-cache" : `t3-task-cache-${stage}`;
13});
14
15export const Index = cacheName.pipe(
16 Effect.flatMap((name) =>
17 Cloudflare.D1.Database("Index", {
18 name,
19 migrations: NodeURL.fileURLToPath(new URL("migrations", protocol)),
20 }).pipe(adopt(true), retain()),
21 ),
22);
23
24export const Artifacts = cacheName.pipe(
25 Effect.flatMap((name) =>
26 Cloudflare.R2.Bucket("Artifacts", {
27 name,
28 lifecycleRules: [
29 {
30 id: "remote-cache-generations",
31 deleteObjectsTransition: { condition: { type: "Age", maxAge: 9 * 86400 } },
32 abortMultipartUploadsTransition: { condition: { type: "Age", maxAge: 86400 } },
33 },
34 ],
35 }).pipe(adopt(true), retain()),
36 ),
37);
38
39// Fingerprint-keyed simulator/emulator dev clients; separate from the 9-day task-cache generations.
40export const NativeClients = cacheName.pipe(
41 Effect.flatMap((name) =>
42 Cloudflare.R2.Bucket("NativeClients", {
43 name: `${name}-native-clients`,
44 lifecycleRules: [
45 {
46 id: "native-client-retention",
47 deleteObjectsTransition: { condition: { type: "Age", maxAge: 30 * 86400 } },
48 abortMultipartUploadsTransition: { condition: { type: "Age", maxAge: 86400 } },
49 },
50 ],
51 }).pipe(retain()),
52 ),
53);
54
55export const Savings = cacheName.pipe(
56 Effect.flatMap((name) =>
57 Cloudflare.D1.Database("Savings", {
58 name: `${name}-savings`,
59 migrations: NodeURL.fileURLToPath(new URL("../migrations/savings", import.meta.url)),
60 }).pipe(retain()),
61 ),
62);