import { assert, describe, it } from "@effect/vitest" import { Context } from "effect" import { HttpApi, HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi" describe("HttpApi", () => { it("stores the supplied identifier", () => { const api = HttpApi.make("Api") assert.strictEqual(api.identifier, "Api") }) it("initializes groups as a readonly record", () => { const api = HttpApi.make("Api") assert.deepStrictEqual(api.groups, {}) }) it("stores __proto__ group and endpoint identifiers as own properties", () => { const group = HttpApiGroup.make("__proto__").add( HttpApiEndpoint.get("__proto__", "/proto") ) const child = HttpApi.make("Child").add(group) const api = HttpApi.make("Api").addHttpApi(child) assert.isTrue(Object.hasOwn(group.endpoints, "__proto__")) assert.isTrue(Object.hasOwn(child.groups, "__proto__")) assert.isTrue(Object.hasOwn(api.groups, "__proto__")) assert.isTrue(Object.hasOwn(api.groups["__proto__"].endpoints, "__proto__")) const reflected: Array = [] HttpApi.reflect(api, { onGroup: ({ group }) => reflected.push(group.identifier), onEndpoint: ({ endpoint }) => reflected.push(endpoint.identifier) }) assert.deepStrictEqual(reflected, ["__proto__", "__proto__"]) }) it("does not mutate groups from the added API", () => { const group = HttpApiGroup.make("users").annotate(OpenApi.Title, "Users") const child = HttpApi.make("Child") .annotate(OpenApi.Description, "Child API") .add(group) const originalAnnotations = group.annotations const parent = HttpApi.make("Parent").addHttpApi(child) assert.strictEqual(group.annotations, originalAnnotations) assert.strictEqual(child.groups.users, group) assert.notStrictEqual(parent.groups.users, group) assert.strictEqual(Context.getUnsafe(parent.groups.users.annotations, OpenApi.Title), "Users") assert.strictEqual(Context.getUnsafe(parent.groups.users.annotations, OpenApi.Description), "Child API") }) it("keeps annotations from API variants isolated", () => { const group = HttpApiGroup.make("users").annotate(OpenApi.Title, "Users") const child = HttpApi.make("Child").add(group) const publicChild = child.annotate(OpenApi.Description, "Public API") const internalChild = child.annotate(OpenApi.Description, "Internal API") const publicParent = HttpApi.make("PublicParent").addHttpApi(publicChild) const internalParent = HttpApi.make("InternalParent").addHttpApi(internalChild) assert.strictEqual(Context.getUnsafe(publicParent.groups.users.annotations, OpenApi.Description), "Public API") assert.strictEqual(Context.getUnsafe(internalParent.groups.users.annotations, OpenApi.Description), "Internal API") assert.notStrictEqual(publicParent.groups.users, internalParent.groups.users) const publicTag = OpenApi.fromApi(publicParent).tags.find((tag) => tag.name === "Users") const internalTag = OpenApi.fromApi(internalParent).tags.find((tag) => tag.name === "Users") assert.isDefined(publicTag) assert.isDefined(internalTag) assert.strictEqual(publicTag.description, "Public API") assert.strictEqual(internalTag.description, "Internal API") }) it("preserves group annotation precedence", () => { const group = HttpApiGroup.make("users").annotate(OpenApi.Title, "Group title") const child = HttpApi.make("Child") .annotate(OpenApi.Title, "API title") .add(group) const parent = HttpApi.make("Parent").addHttpApi(child) assert.strictEqual(Context.getUnsafe(parent.groups.users.annotations, OpenApi.Title), "Group title") }) })