Skip to content
Source
Sign inSign up
Open History to see the last commit

Bindings.test.ts

167 lines4.4 KB

1import * as Cloudflare from "@alchemy.run/cloudflare";
2import { expect } from "@alchemy.run/test";
3import * as Test from "@alchemy.run/test/Alchemy";
4import * as Turso from "@alchemy.run/turso";
5import * as Alchemy from "alchemy";
6import * as Effect from "effect/Effect";
7import * as HttpClient from "effect/http/HttpClient";
8import * as Layer from "effect/Layer";
9import * as Schedule from "effect/Schedule";
10import { BindingDb, TenantGroup } from "./fixtures/resources.ts";
11import TursoWorker from "./fixtures/worker.ts";
12​
13const providers = Layer.mergeAll(Turso.providers(), Cloudflare.providers());
14const { test, beforeAll, afterAll, deploy, destroy } = Test.make({ providers });
15​
16const Stack = Alchemy.Stack(
17 "TursoBindingsStack",
18 { providers, state: Cloudflare.state() },
19 Effect.gen(function* () {
20 const db = yield* BindingDb;
21 const group = yield* TenantGroup;
22 const worker = yield* TursoWorker;
23 return {
24 url: worker.url.as<string>(),
25 group: group.name,
26 organization: group.organization,
27 db: db.name,
28 };
29 }),
30);
31​
32const stack = beforeAll(deploy(Stack));
33afterAll.skipIf(!!process.env.NO_DESTROY)(destroy(Stack));
34​
35const get = (path: string) =>
36 Effect.gen(function* () {
37 const { url } = yield* stack;
38 const client = HttpClient.filterStatusOk(yield* HttpClient.HttpClient);
39 const res = yield* client
40 .get(`${url}${path}`)
41 .pipe(Effect.retry({ schedule: Schedule.exponential("500 millis"), times: 8 }));
42 return yield* res.json;
43 });
44​
45test(
46 "Connect + SQL.LibSQL queries the bound database",
47 Effect.gen(function* () {
48 const body = (yield* get("/sql")) as { count: number };
49 expect(body.count).toBeGreaterThanOrEqual(1);
50 }),
51 {
52 tags: [
53 "provider:turso",
54 "provider:turso:database",
55 "provider:cloudflare",
56 "provider:cloudflare:worker",
57 "live",
58 ],
59 timeout: 120_000,
60 },
61);
62​
63test(
64 "SQL.LibSQL transactions roll back on failure",
65 Effect.gen(function* () {
66 const body = (yield* get("/tx")) as { failed: boolean; before: number; after: number };
67 expect(body.failed).toBe(true);
68 expect(body.after).toBe(body.before);
69 }),
70 {
71 tags: [
72 "provider:turso",
73 "provider:turso:database",
74 "provider:cloudflare",
75 "provider:cloudflare:worker",
76 "live",
77 ],
78 timeout: 120_000,
79 },
80);
81​
82test(
83 "Connect + Drizzle.LibSQL queries the bound database",
84 Effect.gen(function* () {
85 yield* get("/sql");
86 const body = (yield* get("/drizzle")) as { bodies: string[] };
87 expect(body.bodies).toContain("from-drizzle");
88 }),
89 {
90 tags: [
91 "provider:turso",
92 "provider:turso:database",
93 "provider:cloudflare",
94 "provider:cloudflare:worker",
95 "live",
96 ],
97 timeout: 120_000,
98 },
99);
100​
101test(
102 "Drizzle.LibSQL with relations serves db.query",
103 Effect.gen(function* () {
104 const body = (yield* get("/relations")) as {
105 author: { name: string; posts: Array<{ title: string }> };
106 };
107 expect(body.author.name).toBe("ada");
108 expect(body.author.posts.map((p) => p.title)).toEqual(["engines"]);
109 }),
110 {
111 tags: [
112 "provider:turso",
113 "provider:turso:database",
114 "provider:cloudflare",
115 "provider:cloudflare:worker",
116 "live",
117 ],
118 timeout: 120_000,
119 },
120);
121​
122test(
123 "Connect accessors work with @libsql/client directly",
124 Effect.gen(function* () {
125 const body = (yield* get("/client")) as { seven: number };
126 expect(body.seven).toBe(7);
127 }),
128 {
129 tags: [
130 "provider:turso",
131 "provider:turso:database",
132 "provider:cloudflare",
133 "provider:cloudflare:worker",
134 "live",
135 ],
136 timeout: 120_000,
137 },
138);
139​
140test(
141 "ManageDatabases creates, queries, lists, and deletes tenant databases",
142 Effect.gen(function* () {
143 const { group, organization: org } = yield* stack;
144 const name = `${group}-t1`.slice(0, 40);
145 const body = (yield* get(`/tenant?name=${name}`)) as {
146 url: string;
147 value: string;
148 listed: string[];
149 deleted: boolean;
150 };
151 expect(body.url).toBe(`libsql://${name}-${org}.aws-us-east-1.turso.io`);
152 expect(body.value).toBe(name);
153 expect(body.listed).toContain(name);
154 // `deleted` is the Worker's own Platform API lookup after the delete.
155 expect(body.deleted).toBe(true);
156 }),
157 {
158 tags: [
159 "provider:turso",
160 "provider:turso:database",
161 "provider:cloudflare",
162 "provider:cloudflare:worker",
163 "live",
164 ],
165 timeout: 120_000,
166 },
167);