Skip to main content
Glama

Convex MCP server

Official
by get-convex
value.test.ts5.65 kB
import { test, expect, describe } from "vitest"; import { randomBytes } from "crypto"; import { slowBase64ToBigInt, slowBigIntToBase64, modernBase64ToBigInt, modernBigIntToBase64, convexToJson, jsonToConvex, } from "./value.js"; import { compareValues } from "./compare.js"; describe("convexToJson", () => { test("serializes objects", () => { expect( convexToJson({ property: "value", }), ).toEqual({ property: "value" }); }); test("serializes objects created with Object.create", () => { const obj = Object.create(null); obj.property = "value"; expect(convexToJson(obj)).toEqual({ property: "value" }); }); test("serializes objects with BigInt values", () => { expect( convexToJson({ property: BigInt("5151996"), }), ).toEqual({ property: { $integer: "/JxOAAAAAAA=" } }); }); test("throws an error on class instances", () => { expect(() => { convexToJson(new Date(0) as any); }).toThrow(/Date.*is not a supported Convex type/); }); test("throws an error on class instances inside object", () => { expect(() => { convexToJson({ hello: new Date(0) } as any); }).toThrow( /Date.*is not a supported Convex type \(present at path .hello in original object/, ); }); test("throws an informative error on undefined array", () => { expect(() => { convexToJson([undefined] as any); }).toThrow( 'undefined is not a valid Convex value (present at path [0] in original object ["undefined"]).', ); }); test("throws an informative error on undefined", () => { expect(() => { convexToJson(undefined as any); }).toThrow("undefined is not a valid Convex value."); }); test("supports undefined keys in objects", () => { expect( convexToJson({ property: undefined, }), ).toEqual({}); }); // BigInts throw in JSON.stringify, so ensure we can format them in errors. test("doesn't crash on bigint error", () => { expect(() => { convexToJson({ bigint: BigInt("123"), bad: [undefined] } as any); }).toThrow( 'undefined is not a valid Convex value (present at path .bad[0] in original object {"bigint":"123n","bad":["undefined"]})', ); }); }); describe("jsonToConvex", () => { test("deserializes object with BigInt value", () => { expect(jsonToConvex({ property: { $integer: "/JxOAAAAAAA=" } })).toEqual({ property: BigInt("5151996"), }); }); }); describe("bigints in Safari 14", () => { test("roundtrips BigInt even in Safari 14", () => { // https://caniuse.com/mdn-javascript_builtins_dataview_setbigint64 const origGetBigInt64 = DataView.prototype.getBigInt64; const origSetBigInt64 = DataView.prototype.setBigInt64; DataView.prototype.getBigInt64 = () => { throw new Error("doesn't exist in Safari 14"); }; DataView.prototype.setBigInt64 = () => { throw new Error("doesn't exist in Safari 14"); }; try { const orig = "/JxOAAAAAAA="; expect(slowBigIntToBase64(slowBase64ToBigInt(orig))).toEqual(orig); } finally { DataView.prototype.getBigInt64 = origGetBigInt64; DataView.prototype.setBigInt64 = origSetBigInt64; } }); }); const MIN_INT64 = BigInt("-9223372036854775808"); const MAX_INT64 = BigInt("9223372036854775807"); function randomSignedInt64Bigint() { return BigInt("0x" + randomBytes(8).toString("hex")) + MIN_INT64; } describe("Our hand-rolled bigint code matches the fast implementation", () => { test("bigInt to bytes to bigint match", () => { const tests = [ BigInt("0"), BigInt("1"), BigInt("-1"), MAX_INT64, MIN_INT64, ...[...Array(100).keys()].map(randomSignedInt64Bigint), ]; for (const num of tests) { const expectedS = modernBigIntToBase64(num); const s = slowBigIntToBase64(num); expect(s).toEqual(expectedS); const numAgain = slowBase64ToBigInt(s); expect(numAgain).toEqual(modernBase64ToBigInt(s)); expect(numAgain).toEqual(num); } }); }); describe("compare", () => { test("NaNs and negative zero", () => { const positiveNaN = Number.NaN; // Create DataViews for bit-level comparison const buffer = new ArrayBuffer(8); new DataView(buffer).setFloat64(0, positiveNaN, /* little-endian */ true); // Read as BigInt to compare bits const v1Bits = BigInt( new DataView(buffer).getBigInt64(0, /* little-endian */ true), ); // Flip the sign bit const negativeNaNBits = v1Bits | 0x8000000000000000n; // Convert back to a number const negativeNaNBuffer = new ArrayBuffer(8); new DataView(negativeNaNBuffer).setBigInt64( 0, negativeNaNBits, /* little-endian */ true, ); const negativeNaN = new DataView(negativeNaNBuffer).getFloat64( 0, /* little-endian */ true, ); const values = [negativeNaN, -0, 0, 1, positiveNaN]; function repr(v: number) { if (v === 0) { return "-NaN"; } if (v === 1) { return "-0"; } if (v === 2) { return "0"; } if (v === 3) { return "1"; } if (v === 4) { return "+NaN"; } } for (let i = 0; i < values.length; i++) { for (let j = i + 1; j < values.length; j++) { const v1 = values[i]; const v2 = values[j]; expect(compareValues(v1, v2), `compare ${repr(i)} ${repr(j)}`).toEqual( -1, ); expect(compareValues(v2, v1), `compare ${repr(j)} ${repr(i)}`).toEqual( 1, ); } } }); });

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/get-convex/convex-backend'

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