diff --git a/.changeset/clever-dolphins-return.md b/.changeset/clever-dolphins-return.md new file mode 100644 index 000000000..275c45a27 --- /dev/null +++ b/.changeset/clever-dolphins-return.md @@ -0,0 +1,5 @@ +--- +"inngest": patch +--- + +Fix failing to parse `BigInt` during step/function result serialization; it is now correctly typed and returned as `never` diff --git a/packages/inngest/src/components/InngestStepTools.test.ts b/packages/inngest/src/components/InngestStepTools.test.ts index 144abbab5..c74d496d3 100644 --- a/packages/inngest/src/components/InngestStepTools.test.ts +++ b/packages/inngest/src/components/InngestStepTools.test.ts @@ -195,28 +195,52 @@ describe("run", () => { symbol: Symbol("foo"), map: new Map(), set: new Set(), + bigint: BigInt(123), + typedArray: new Int8Array(2), + promise: Promise.resolve(), + weakMap: new WeakMap([[{}, "test"]]), + weakSet: new WeakSet([{}]), }; const output = step.run("step", () => input); - assertType< - Promise<{ + type Expected = { + str: string; + num: number; + bool: boolean; + date: string; + obj: { str: string; num: number; - bool: boolean; - date: string; - obj: { - str: string; - num: number; - }; - arr: (number | null | boolean)[]; - infinity: number; - nan: number; - null: null; - map: Record; - set: Record; - }> - >(output); + }; + arr: (number | null | boolean)[]; + infinity: number; + nan: number; + null: null; + map: Record; + set: Record; + bigint: never; + typedArray: Record; + // eslint-disable-next-line @typescript-eslint/ban-types + promise: {}; + // eslint-disable-next-line @typescript-eslint/ban-types + weakMap: {}; + // eslint-disable-next-line @typescript-eslint/ban-types + weakSet: {}; + }; + + assertType>(output); + + /** + * Used to ensure that stripped base properties are also adhered to. + */ + type KeysMatchExactly = keyof T extends keyof U + ? keyof U extends keyof T + ? true + : false + : false; + + assertType>>(true); }); }); diff --git a/packages/inngest/src/helpers/strings.test.ts b/packages/inngest/src/helpers/strings.test.ts index 3d669875e..08a298fc4 100644 --- a/packages/inngest/src/helpers/strings.test.ts +++ b/packages/inngest/src/helpers/strings.test.ts @@ -1,4 +1,4 @@ -import { slugify, timeStr } from "@local/helpers/strings"; +import { slugify, stringify, timeStr } from "@local/helpers/strings"; describe("slugify", () => { it("Generates a slug using hyphens", () => { @@ -42,3 +42,9 @@ describe("timeStr", () => { expect(timeStr(new Date(0))).toEqual("1970-01-01T00:00:00.000Z"); }); }); + +describe("stringify", () => { + test("removes BigInt", () => { + expect(stringify({ a: BigInt(1), b: 2 })).toEqual(JSON.stringify({ b: 2 })); + }); +}); diff --git a/packages/inngest/src/helpers/strings.ts b/packages/inngest/src/helpers/strings.ts index a757c64f8..61d33079e 100644 --- a/packages/inngest/src/helpers/strings.ts +++ b/packages/inngest/src/helpers/strings.ts @@ -1,7 +1,21 @@ import { sha256 } from "hash.js"; +import { default as safeStringify } from "json-stringify-safe"; import ms from "ms"; import { type TimeStr } from "../types"; -export { default as stringify } from "json-stringify-safe"; + +/** + * Safely `JSON.stringify()` an `input`, handling circular refernences and + * removing `BigInt` values. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const stringify = (input: any): string => { + return safeStringify(input, (key, value) => { + if (typeof value !== "bigint") { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return value; + } + }); +}; /** * Returns a slugified string used to generate consistent IDs.