Skip to content

Commit a790759

Browse files
matt-aitkennicktrnericallam
authored
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>
1 parent 7f9091f commit a790759

File tree

3 files changed

+45
-18
lines changed

3 files changed

+45
-18
lines changed

.github/workflows/unit-tests.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ jobs:
3838
SESSION_SECRET: "secret"
3939
MAGIC_LINK_SECRET: "secret"
4040
ENCRYPTION_KEY: "secret"
41-
41+
42+
- name: 🧪 Run Package Unit Tests
43+
run: pnpm run test --filter "@trigger.dev/*"
4244

4345
- name: 🧪 Run Internal Unit Tests
4446
run: pnpm run test --filter "@internal/*"

packages/core/src/v3/utils/flattenAttributes.ts

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -95,36 +95,47 @@ export function unflattenAttributes(
9595
const result: Record<string, unknown> = {};
9696

9797
for (const [key, value] of Object.entries(obj)) {
98-
const parts = key.split(".").reduce((acc, part) => {
99-
if (part.includes("[")) {
100-
// Handling nested array indices
101-
const subparts = part.split(/\[|\]/).filter((p) => p !== "");
102-
acc.push(...subparts);
103-
} else {
104-
acc.push(part);
105-
}
106-
return acc;
107-
}, [] as string[]);
98+
const parts = key.split(".").reduce(
99+
(acc, part) => {
100+
if (part.startsWith("[") && part.endsWith("]")) {
101+
// Handle array indices more precisely
102+
const match = part.match(/^\[(\d+)\]$/);
103+
if (match && match[1]) {
104+
acc.push(parseInt(match[1]));
105+
} else {
106+
// Remove brackets for non-numeric array keys
107+
acc.push(part.slice(1, -1));
108+
}
109+
} else {
110+
acc.push(part);
111+
}
112+
return acc;
113+
},
114+
[] as (string | number)[]
115+
);
108116

109117
let current: any = result;
110118
for (let i = 0; i < parts.length - 1; i++) {
111119
const part = parts[i];
120+
const nextPart = parts[i + 1];
112121

113-
if (!part) {
122+
if (!part && part !== 0) {
114123
continue;
115124
}
116125

117-
const nextPart = parts[i + 1];
118-
const isArray = nextPart && /^\d+$/.test(nextPart);
119-
if (isArray && !Array.isArray(current[part])) {
120-
current[part] = [];
121-
} else if (!isArray && current[part] === undefined) {
126+
if (typeof nextPart === "number") {
127+
// Ensure we create an array for numeric indices
128+
current[part] = Array.isArray(current[part]) ? current[part] : [];
129+
} else if (current[part] === undefined) {
130+
// Create an object for non-numeric paths
122131
current[part] = {};
123132
}
133+
124134
current = current[part];
125135
}
136+
126137
const lastPart = parts[parts.length - 1];
127-
if (lastPart) {
138+
if (lastPart !== undefined) {
128139
current[lastPart] = rehydrateNull(value);
129140
}
130141
}

packages/core/test/flattenAttributes.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
import { flattenAttributes, unflattenAttributes } from "../src/v3/utils/flattenAttributes.js";
22

33
describe("flattenAttributes", () => {
4+
it("handles number keys correctl", () => {
5+
expect(flattenAttributes({ bar: { "25": "foo" } })).toEqual({ "bar.25": "foo" });
6+
expect(unflattenAttributes({ "bar.25": "foo" })).toEqual({ bar: { "25": "foo" } });
7+
expect(flattenAttributes({ bar: ["foo", "baz"] })).toEqual({
8+
"bar.[0]": "foo",
9+
"bar.[1]": "baz",
10+
});
11+
expect(unflattenAttributes({ "bar.[0]": "foo", "bar.[1]": "baz" })).toEqual({
12+
bar: ["foo", "baz"],
13+
});
14+
expect(flattenAttributes({ bar: { 25: "foo" } })).toEqual({ "bar.25": "foo" });
15+
expect(unflattenAttributes({ "bar.25": "foo" })).toEqual({ bar: { 25: "foo" } });
16+
});
17+
418
it("handles null correctly", () => {
519
expect(flattenAttributes(null)).toEqual({ "": "$@null((" });
620
expect(unflattenAttributes({ "": "$@null((" })).toEqual(null);

0 commit comments

Comments
 (0)