| 1 | import * as Alchemy from "alchemy"; |
| 2 | import * as Cloudflare from "alchemy/Cloudflare"; |
| 3 | import * as Neon from "alchemy/Neon"; |
| 4 | import * as Test from "alchemy/Test/Alchemy"; |
| 5 | import { expect } from "alchemy-test"; |
| 6 | import * as Effect from "effect/Effect"; |
| 7 | import * as Layer from "effect/Layer"; |
| 8 | import HyperdriveAuthWorker from "./fixtures/hyperdrive-worker.ts"; |
| 9 | import { |
| 10 | AuthHttpError, |
| 11 | edgeRetry, |
| 12 | getJson, |
| 13 | postJson, |
| 14 | toCookieHeader, |
| 15 | } from "../http.ts"; |
| 16 | |
| 17 | const providers = Layer.mergeAll(Cloudflare.providers(), Neon.providers()); |
| 18 | const { test, beforeAll, afterAll, deploy, destroy } = Test.make({ |
| 19 | providers, |
| 20 | }); |
| 21 | |
| 22 | const Stack = Alchemy.Stack( |
| 23 | "BetterAuthHdTestStack", |
| 24 | { providers, state: Cloudflare.state() }, |
| 25 | Effect.gen(function* () { |
| 26 | const worker = yield* HyperdriveAuthWorker; |
| 27 | return { url: worker.url.as<string>() }; |
| 28 | }), |
| 29 | ); |
| 30 | |
| 31 | const stack = beforeAll(deploy(Stack)); |
| 32 | afterAll.skipIf(!!process.env.NO_DESTROY)(destroy(Stack)); |
| 33 | |
| 34 | test( |
| 35 | "Worker -> Postgres through Hyperdrive (pg on workerd, origin-URL migrations)", |
| 36 | Effect.gen(function* () { |
| 37 | const { url } = yield* stack; |
| 38 | const email = "hyperdrive@example.com"; |
| 39 | const password = "password1234"; |
| 40 | |
| 41 | yield* postJson(`${url}/auth/sign-up/email`, { |
| 42 | email, |
| 43 | password, |
| 44 | name: "Hyperdrive User", |
| 45 | }).pipe( |
| 46 | Effect.filterOrFail( |
| 47 | (response) => |
| 48 | response.status === 200 || |
| 49 | response.body.includes("USER_ALREADY_EXISTS"), |
| 50 | (response) => new AuthHttpError({ url, ...response }), |
| 51 | ), |
| 52 | edgeRetry, |
| 53 | ); |
| 54 | |
| 55 | const signIn = yield* postJson(`${url}/auth/sign-in/email`, { |
| 56 | email, |
| 57 | password, |
| 58 | }).pipe( |
| 59 | Effect.filterOrFail( |
| 60 | (response) => response.status === 200, |
| 61 | (response) => new AuthHttpError({ url, ...response }), |
| 62 | ), |
| 63 | ); |
| 64 | expect(signIn.setCookies.length).toBeGreaterThan(0); |
| 65 | |
| 66 | const me = yield* getJson<{ email: string | null }>(`${url}/me`, { |
| 67 | cookie: toCookieHeader(signIn.setCookies), |
| 68 | }); |
| 69 | expect(me.email).toBe(email); |
| 70 | }), |
| 71 | { |
| 72 | tags: [ |
| 73 | "provider:cloudflare", |
| 74 | "provider:cloudflare:hyperdrive", |
| 75 | "provider:cloudflare:worker", |
| 76 | "provider:neon", |
| 77 | "provider:neon:project", |
| 78 | "live", |
| 79 | ], |
| 80 | timeout: 120_000, |
| 81 | }, |
| 82 | ); |