1import { inMemoryState } from "@/State/InMemoryState.ts";
2import type { ResourceState } from "@/State/ResourceState.ts";
3import { deleteState, listState, readState } from "@/State/Tree.ts";
4import { describe, expect, it } from "alchemy-test";
5import * as Effect from "effect/Effect";
6
7const resource = {
8 resourceType: "test:resource",
9 namespace: undefined,
10 fqn: "resource",
11 logicalId: "resource",
12 instanceId: "instance-resource",
13 providerVersion: 1,
14 status: "created",
15 downstream: [],
16 bindings: [],
17 props: {},
18 attr: { value: 1 },
19} as ResourceState;
20
21const state = () =>
22 inMemoryState(
23 { app: { dev: { resource } } },
24 { app: { dev: { url: "https://example.com" } } },
25 );
26
27describe("State tree", { tags: ["unit", "local"] }, () => {
28 it.effect("queries state as structured data", () =>
29 Effect.gen(function* () {
30 expect(yield* listState({})).toEqual(["app/"]);
31 expect(yield* listState({ path: "app/dev", recursive: true })).toEqual([
32 "app/dev/resource",
33 "app/dev/output",
34 ]);
35
36 expect(yield* readState({ path: "app/dev/output" })).toEqual([
37 {
38 path: "app/dev/output",
39 kind: "output",
40 value: { url: "https://example.com" },
41 },
42 ]);
43 }).pipe(Effect.provide(state())),
44 );
45
46 it.effect("deletes subtrees and reports what was removed", () =>
47 Effect.gen(function* () {
48 const deleted = yield* deleteState({ path: "app/dev", recursive: true });
49
50 expect(deleted).toEqual({
51 _tag: "StateDeleted",
52 path: "app/dev",
53 deleted: ["app/dev/resource", "app/dev/output"],
54 });
55 expect(yield* listState({ path: "app" })).toEqual([]);
56 }).pipe(Effect.provide(state())),
57 );
58});