Skip to main content
Glama

Bucket Feature Flags MCP Server

Official
by reflagcom
json.test.ts13.1 kB
import { describe, expect, it } from "vitest"; import { JSONToType, mergeTypeASTs, quoteKey, stringifyTypeAST, toTypeAST, TypeAST, } from "../utils/json.js"; describe("JSON utilities", () => { describe("toTypeAST", () => { it("should handle primitive values", () => { expect(toTypeAST("test")).toEqual({ kind: "primitive", type: "string" }); expect(toTypeAST(42)).toEqual({ kind: "primitive", type: "number" }); expect(toTypeAST(true)).toEqual({ kind: "primitive", type: "boolean" }); expect(toTypeAST(null)).toEqual({ kind: "primitive", type: "null" }); }); it("should handle arrays", () => { expect(toTypeAST([1, 2, 3])).toEqual({ kind: "array", elementType: { kind: "primitive", type: "number" }, }); expect(toTypeAST([])).toEqual({ kind: "array", elementType: { kind: "primitive", type: "any" }, }); }); it("should handle arrays with mixed element types", () => { expect(toTypeAST([1, "test", true])).toEqual({ kind: "array", elementType: { kind: "union", types: [ { kind: "primitive", type: "number" }, { kind: "primitive", type: "string" }, { kind: "primitive", type: "boolean" }, ], }, }); expect(toTypeAST([{ name: "John" }, { age: 30 }])).toEqual({ kind: "array", elementType: { kind: "object", properties: [ { key: "name", type: { kind: "primitive", type: "string" }, optional: true, }, { key: "age", type: { kind: "primitive", type: "number" }, optional: true, }, ], }, }); }); it("should handle objects", () => { expect(toTypeAST({ name: "John", age: 30 })).toEqual({ kind: "object", properties: [ { key: "name", type: { kind: "primitive", type: "string" }, optional: false, }, { key: "age", type: { kind: "primitive", type: "number" }, optional: false, }, ], }); }); it("should handle nested structures", () => { const input = { user: { name: "John", contacts: [{ email: "john@example.com" }], }, }; const expected: TypeAST = { kind: "object", properties: [ { key: "user", type: { kind: "object", properties: [ { key: "name", type: { kind: "primitive", type: "string" }, optional: false, }, { key: "contacts", type: { kind: "array", elementType: { kind: "object", properties: [ { key: "email", type: { kind: "primitive", type: "string" }, optional: false, }, ], }, }, optional: false, }, ], }, optional: false, }, ], }; expect(toTypeAST(input)).toEqual(expected); }); }); describe("mergeTypeASTs", () => { it("should handle empty array", () => { expect(mergeTypeASTs([])).toEqual({ kind: "primitive", type: "any" }); }); it("should return the same AST for single item arrays", () => { const ast: TypeAST = { kind: "primitive", type: "string" }; expect(mergeTypeASTs([ast])).toEqual(ast); }); it("should merge same primitive types", () => { const types: TypeAST[] = [ { kind: "primitive", type: "number" }, { kind: "primitive", type: "number" }, ]; expect(mergeTypeASTs(types)).toEqual({ kind: "primitive", type: "number", }); }); it("should create union for different primitive types", () => { const types: TypeAST[] = [ { kind: "primitive", type: "string" }, { kind: "primitive", type: "number" }, ]; expect(mergeTypeASTs(types)).toEqual({ kind: "union", types: [ { kind: "primitive", type: "string" }, { kind: "primitive", type: "number" }, ], }); }); it("should merge array types", () => { const types: TypeAST[] = [ { kind: "array", elementType: { kind: "primitive", type: "number" } }, { kind: "array", elementType: { kind: "primitive", type: "string" } }, ]; expect(mergeTypeASTs(types)).toEqual({ kind: "array", elementType: { kind: "union", types: [ { kind: "primitive", type: "number" }, { kind: "primitive", type: "string" }, ], }, }); }); it("should merge object types and mark missing properties as optional", () => { const types: TypeAST[] = [ { kind: "object", properties: [ { key: "name", type: { kind: "primitive", type: "string" }, optional: false, }, { key: "age", type: { kind: "primitive", type: "number" }, optional: false, }, ], }, { kind: "object", properties: [ { key: "name", type: { kind: "primitive", type: "string" }, optional: false, }, { key: "email", type: { kind: "primitive", type: "string" }, optional: false, }, ], }, ]; expect(mergeTypeASTs(types)).toEqual({ kind: "object", properties: [ { key: "name", type: { kind: "primitive", type: "string" }, optional: false, }, { key: "age", type: { kind: "primitive", type: "number" }, optional: true, }, { key: "email", type: { kind: "primitive", type: "string" }, optional: true, }, ], }); }); it("should create union for mixed kinds", () => { const types: TypeAST[] = [ { kind: "primitive", type: "string" }, { kind: "array", elementType: { kind: "primitive", type: "number" } }, ]; expect(mergeTypeASTs(types)).toEqual({ kind: "union", types, }); }); }); describe("stringifyTypeAST", () => { it("should stringify primitive types", () => { expect(stringifyTypeAST({ kind: "primitive", type: "string" })).toBe( "string", ); expect(stringifyTypeAST({ kind: "primitive", type: "number" })).toBe( "number", ); expect(stringifyTypeAST({ kind: "primitive", type: "boolean" })).toBe( "boolean", ); expect(stringifyTypeAST({ kind: "primitive", type: "null" })).toBe( "null", ); }); it("should stringify array types", () => { expect( stringifyTypeAST({ kind: "array", elementType: { kind: "primitive", type: "string" }, }), ).toBe("(string)[]"); }); it("should stringify object types", () => { const ast: TypeAST = { kind: "object", properties: [ { key: "name", type: { kind: "primitive", type: "string" }, optional: false, }, { key: "age", type: { kind: "primitive", type: "number" }, optional: true, }, ], }; const expected = `{\n name: string,\n age?: number\n}`; expect(stringifyTypeAST(ast)).toBe(expected); }); it("should stringify empty objects", () => { expect(stringifyTypeAST({ kind: "object", properties: [] })).toBe("{}"); }); it("should quote object keys with special characters", () => { const ast: TypeAST = { kind: "object", properties: [ { key: "my-key", type: { kind: "primitive", type: "string" }, optional: false, }, { key: "my key", type: { kind: "primitive", type: "string" }, optional: false, }, { key: "my.key", type: { kind: "primitive", type: "string" }, optional: false, }, { key: "123key", type: { kind: "primitive", type: "string" }, optional: false, }, ], }; const expected = `{\n "my-key": string,\n "my key": string,\n "my.key": string,\n "123key": string\n}`; expect(stringifyTypeAST(ast)).toBe(expected); }); it("should stringify union types", () => { const ast: TypeAST = { kind: "union", types: [ { kind: "primitive", type: "string" }, { kind: "primitive", type: "number" }, ], }; expect(stringifyTypeAST(ast)).toBe("string | number"); }); it("should handle complex nested types", () => { const ast: TypeAST = { kind: "object", properties: [ { key: "user", type: { kind: "object", properties: [ { key: "name", type: { kind: "primitive", type: "string" }, optional: false, }, { key: "contacts", type: { kind: "array", elementType: { kind: "object", properties: [ { key: "email", type: { kind: "primitive", type: "string" }, optional: false, }, ], }, }, optional: false, }, ], }, optional: false, }, ], }; const expected = `{\n user: {\n name: string,\n contacts: ({\n email: string\n })[]` + `\n }\n}`; expect(stringifyTypeAST(ast)).toBe(expected); }); }); describe("JSONToType", () => { it("should handle empty arrays", () => { expect(JSONToType([])).toBeNull(); }); it("should generate type for array of primitives", () => { expect(JSONToType([1, 2, 3])).toBe("number"); expect(JSONToType(["a", "b", "c"])).toBe("string"); expect(JSONToType([1, "a", true])).toBe("number | string | boolean"); }); it("should handle arrays with simple mixed element types", () => { const expected = "(number | string | boolean)[]"; expect(JSONToType([["a", true], [1]])).toBe(expected); }); it("should handle arrays with advanced mixed element types", () => { const expected = "(number | string | boolean | {\n id?: number,\n name?: string\n})[]"; expect( JSONToType([ [1, "a", true], [{ id: 1 }, { name: "test" }], ]), ).toBe(expected); }); it("should merge arrays with nested arrays of mixed element types", () => { const expected = "((boolean | number | string | {\n id: number\n})[])[]"; expect(JSONToType([[[1, "test"], [true]], [[{ id: 1 }]]])).toBe(expected); }); it("should generate type for array of objects", () => { const expected = `{\n name: string,\n age?: number,\n email?: string\n}`; expect( JSONToType([ { name: "John", age: 30 }, { name: "Jane", email: "jane@example.com" }, ]), ).toBe(expected); }); it("should handle complex nested structures", () => { const expected = `{\n user: {\n name: string,\n settings: {\n theme?: string,` + `\n notifications?: boolean\n }\n }\n}`; expect( JSONToType([ { user: { name: "John", settings: { theme: "dark" }, }, }, { user: { name: "Jane", settings: { notifications: true }, }, }, ]), ).toBe(expected); }); }); describe("quoteKey", () => { it("should quote keys with special characters", () => { expect(quoteKey("my-key")).toBe('"my-key"'); expect(quoteKey("my key")).toBe('"my key"'); expect(quoteKey("my.key")).toBe('"my.key"'); expect(quoteKey("123key")).toBe('"123key"'); expect(quoteKey("key")).toBe("key"); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/reflagcom/bucket-javascript-sdk'

If you have feedback or need assistance with the MCP directory API, please join our Discord server