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:
@@ -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/*"
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user