1import { providers } from "@/Neon/Providers";
2import { bucketStorageClient } from "@/Neon/Bucket";
3import * as Test from "@/Test/Alchemy";
4import * as SDK from "@distilled.cloud/neon";
5import { expect } from "alchemy-test";
6import * as Effect from "effect/Effect";
7import * as HttpClient from "effect/http/HttpClient";
8import StorageFunction from "./fixtures/StorageFunction.ts";
9import { StorageBucket, StorageSettings } from "./fixtures/StorageResources.ts";
10
11const { test } = Test.make({ providers: providers(), dev: true });
12
13test.provider(
14 "local Function uses managed storage credentials through the RPC sidecar",
15 (stack) =>
16 Effect.gen(function* () {
17 yield* stack.destroy();
18 const { fn, bucket } = yield* stack.deploy(
19 Effect.gen(function* () {
20 const bucket = yield* StorageBucket;
21 yield* StorageSettings;
22 return { fn: yield* StorageFunction, bucket };
23 }),
24 );
25 expect(fn.functionId.startsWith("dev:")).toBe(true);
26 const http = HttpClient.filterStatusOk(yield* HttpClient.HttpClient);
27 expect(yield* (yield* http.get(fn.url)).json).toEqual({
28 theme: "system",
29 pageSize: 25,
30 });
31 const written = yield* (yield* HttpClient.HttpClient).get(
32 `${fn.url}/write`,
33 );
34 if (written.status !== 200)
35 yield* Effect.log("Storage write failed", {
36 tag: written.headers["x-storage-error"] ?? "unclassified",
37 });
38 expect(written.status).toBe(200);
39 expect(yield* (yield* http.get(fn.url)).json).toEqual({
40 theme: "dark",
41 pageSize: 50,
42 });
43 expect(
44 (yield* (yield* bucketStorageClient(bucket)).head("settings.json"))
45 ?.ContentType,
46 ).toBe("application/json");
47 const credentials = (yield* SDK.listCredentials({
48 project_id: bucket.projectId,
49 branch_id: bucket.branchId,
50 })).credentials;
51 expect(
52 credentials.filter(
53 (credential) =>
54 credential.branch_id === bucket.branchId && !credential.revoked_at,
55 ).length,
56 ).toBe(3);
57 yield* stack.destroy();
58 yield* stack.destroy();
59 }),
60 {
61 tags: [
62 "provider:neon",
63 "provider:neon:branch",
64 "provider:neon:bucket",
65 "provider:neon:function",
66 "provider:neon:object",
67 "provider:neon:project",
68 "live",
69 ],
70 timeout: 120_000,
71 },
72);