Unflattening array fix for very large arrays (#1432)

* fix unflattening of array indices

* Get tests passing

---------

Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
Co-authored-by: Eric Allam <eallam@icloud.com>
This commit is contained in:
Matt Aitken
2024-10-23 20:58:02 +01:00
committed by GitHub
parent 7f9091f205
commit a79075908e
3 changed files with 45 additions and 18 deletions
+3 -1
View File
@@ -38,7 +38,9 @@ jobs:
SESSION_SECRET: "secret"
MAGIC_LINK_SECRET: "secret"
ENCRYPTION_KEY: "secret"
- name: 🧪 Run Package Unit Tests
run: pnpm run test --filter "@trigger.dev/*"
- name: 🧪 Run Internal Unit Tests
run: pnpm run test --filter "@internal/*"
+28 -17
View File
@@ -95,36 +95,47 @@ export function unflattenAttributes(
const result: Record<string, unknown> = {};
for (const [key, value] of Object.entries(obj)) {
const parts = key.split(".").reduce((acc, part) => {
if (part.includes("[")) {
// Handling nested array indices
const subparts = part.split(/\[|\]/).filter((p) => p !== "");
acc.push(...subparts);
} else {
acc.push(part);
}
return acc;
}, [] as string[]);
const parts = key.split(".").reduce(
(acc, part) => {
if (part.startsWith("[") && part.endsWith("]")) {
// Handle array indices more precisely
const match = part.match(/^\[(\d+)\]$/);
if (match && match[1]) {
acc.push(parseInt(match[1]));
} else {
// Remove brackets for non-numeric array keys
acc.push(part.slice(1, -1));
}
} else {
acc.push(part);
}
return acc;
},
[] as (string | number)[]
);
let current: any = result;
for (let i = 0; i < parts.length - 1; i++) {
const part = parts[i];
const nextPart = parts[i + 1];
if (!part) {
if (!part && part !== 0) {
continue;
}
const nextPart = parts[i + 1];
const isArray = nextPart && /^\d+$/.test(nextPart);
if (isArray && !Array.isArray(current[part])) {
current[part] = [];
} else if (!isArray && current[part] === undefined) {
if (typeof nextPart === "number") {
// Ensure we create an array for numeric indices
current[part] = Array.isArray(current[part]) ? current[part] : [];
} else if (current[part] === undefined) {
// Create an object for non-numeric paths
current[part] = {};
}
current = current[part];
}
const lastPart = parts[parts.length - 1];
if (lastPart) {
if (lastPart !== undefined) {
current[lastPart] = rehydrateNull(value);
}
}
@@ -1,6 +1,20 @@
import { flattenAttributes, unflattenAttributes } from "../src/v3/utils/flattenAttributes.js";
describe("flattenAttributes", () => {
it("handles number keys correctl", () => {
expect(flattenAttributes({ bar: { "25": "foo" } })).toEqual({ "bar.25": "foo" });
expect(unflattenAttributes({ "bar.25": "foo" })).toEqual({ bar: { "25": "foo" } });
expect(flattenAttributes({ bar: ["foo", "baz"] })).toEqual({
"bar.[0]": "foo",
"bar.[1]": "baz",
});
expect(unflattenAttributes({ "bar.[0]": "foo", "bar.[1]": "baz" })).toEqual({
bar: ["foo", "baz"],
});
expect(flattenAttributes({ bar: { 25: "foo" } })).toEqual({ "bar.25": "foo" });
expect(unflattenAttributes({ "bar.25": "foo" })).toEqual({ bar: { 25: "foo" } });
});
it("handles null correctly", () => {
expect(flattenAttributes(null)).toEqual({ "": "$@null((" });
expect(unflattenAttributes({ "": "$@null((" })).toEqual(null);