Skip to content

Commit

Permalink
Fix stringify() failing to serialize BigInt; remove instead (#375)
Browse files Browse the repository at this point in the history
## Summary
<!-- Succinctly describe your change, providing context, what you've
changed, and why. -->


[`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)s
are not natively parsed by JSON. Attempting to return a `BigInt` from a
step or function will throw an error. This error was hard to see, which
is fixed in #374.

Our types reflect that `BigInt` is unparseable and will type it as
`never`, though these were obscured from the user a touch, which is
fixed in #371.

For this reason, this PR ensures `BigInt`s are removed during parsing
instead of throwing. We can investigate adding `BigInt` support across
our SDKs past this fix; the `n` suffix seems an unwritten standard.

## Checklist
<!-- Tick these items off as you progress. -->
<!-- If an item isn't applicable, ideally please strikeout the item by
wrapping it in "~~"" and suffix it with "N/A My reason for skipping
this." -->
<!-- e.g. "- [ ] ~~Added tests~~ N/A Only touches docs" -->

- [ ] ~~Added a [docs PR](https://github.com/inngest/website) that
references this PR~~ N/A
- [x] Added unit/integration tests
- [x] Added changesets if applicable

## Related

- #371
- #374
  • Loading branch information
jpwilliams authored Oct 26, 2023
1 parent dcafc2b commit e19f9b4
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .changeset/clever-dolphins-return.md
Original file line number Diff line number Diff line change
@@ -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`
56 changes: 40 additions & 16 deletions packages/inngest/src/components/InngestStepTools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, never>;
set: Record<string, never>;
}>
>(output);
};
arr: (number | null | boolean)[];
infinity: number;
nan: number;
null: null;
map: Record<string, never>;
set: Record<string, never>;
bigint: never;
typedArray: Record<string, number>;
// 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<Promise<Expected>>(output);

/**
* Used to ensure that stripped base properties are also adhered to.
*/
type KeysMatchExactly<T, U> = keyof T extends keyof U
? keyof U extends keyof T
? true
: false
: false;

assertType<KeysMatchExactly<Expected, Awaited<typeof output>>>(true);
});
});

Expand Down
8 changes: 7 additions & 1 deletion packages/inngest/src/helpers/strings.test.ts
Original file line number Diff line number Diff line change
@@ -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", () => {
Expand Down Expand Up @@ -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 }));
});
});
16 changes: 15 additions & 1 deletion packages/inngest/src/helpers/strings.ts
Original file line number Diff line number Diff line change
@@ -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.
Expand Down

0 comments on commit e19f9b4

Please sign in to comment.