Skip to content

Commit 4df6886

Browse files
committed
chore: add reduceMap helper
1 parent aee7b4b commit 4df6886

File tree

2 files changed

+141
-1
lines changed

2 files changed

+141
-1
lines changed

packages/shared/filter-commons/src/__tests__/condition-utils.spec.ts

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ jest.mock("mendix/filters/builders");
22

33
import { AndCondition } from "mendix/filters";
44
import { equals, literal } from "mendix/filters/builders";
5-
import { compactArray, fromCompactArray, tag } from "../condition-utils";
5+
import { compactArray, fromCompactArray, reduceMap, tag } from "../condition-utils";
66

77
describe("condition-utils", () => {
88
describe("compactArray", () => {
@@ -47,4 +47,92 @@ describe("condition-utils", () => {
4747
expect(result).toEqual(input);
4848
});
4949
});
50+
51+
describe("reduceMap", () => {
52+
it("returns undefined condition and correct metadata for map with undefined values", () => {
53+
const input = { x: undefined, y: undefined };
54+
const [condition, metadata] = reduceMap(input);
55+
56+
expect(condition).toBeUndefined();
57+
58+
const parsedMeta = JSON.parse(metadata);
59+
expect(parsedMeta).toEqual({
60+
length: 0,
61+
keys: ["x", "y"]
62+
});
63+
});
64+
65+
it("returns single condition and correct metadata for map with one condition", () => {
66+
const tagCondition = tag("test");
67+
const input = { a: tagCondition, b: undefined, c: undefined };
68+
const [condition, metadata] = reduceMap(input);
69+
70+
expect(condition).toBe(tagCondition);
71+
72+
const parsedMeta = JSON.parse(metadata);
73+
expect(parsedMeta).toEqual({
74+
length: 1,
75+
keys: ["a", "b", "c"],
76+
0: "a"
77+
});
78+
});
79+
80+
it("returns 'and' condition and correct metadata for map with multiple conditions", () => {
81+
const tagCondition1 = tag("test1");
82+
const tagCondition2 = tag("test2");
83+
const input = { x: tagCondition1, y: undefined, z: tagCondition2, w: undefined };
84+
const [condition, metadata] = reduceMap(input);
85+
86+
expect(condition).toMatchObject({ name: "and", type: "function" });
87+
expect((condition as AndCondition).args).toHaveLength(2);
88+
expect((condition as AndCondition).args[0]).toBe(tagCondition1);
89+
expect((condition as AndCondition).args[1]).toBe(tagCondition2);
90+
91+
const parsedMeta = JSON.parse(metadata);
92+
expect(parsedMeta).toEqual({
93+
length: 2,
94+
keys: ["x", "y", "z", "w"],
95+
0: "x",
96+
1: "z"
97+
});
98+
});
99+
100+
it("returns undefined condition for empty map", () => {
101+
const input = {};
102+
const [condition, metadata] = reduceMap(input);
103+
104+
expect(condition).toBeUndefined();
105+
106+
const parsedMeta = JSON.parse(metadata);
107+
expect(parsedMeta).toEqual({
108+
length: 0,
109+
keys: []
110+
});
111+
});
112+
113+
it("handles map with mixed condition types", () => {
114+
const tagCondition = tag("tag-test");
115+
const equalsCondition = equals(literal("field"), literal("value"));
116+
const input = {
117+
tag: tagCondition,
118+
equals: equalsCondition,
119+
empty: undefined,
120+
another: undefined
121+
};
122+
const [condition, metadata] = reduceMap(input);
123+
124+
expect(condition).toMatchObject({ name: "and", type: "function" });
125+
expect((condition as AndCondition).args).toHaveLength(2);
126+
expect((condition as AndCondition).args[0]).toBe(tagCondition);
127+
expect((condition as AndCondition).args[1]).toBe(equalsCondition);
128+
129+
const parsedMeta = JSON.parse(metadata);
130+
expect(parsedMeta).toEqual({
131+
length: 2,
132+
keys: ["tag", "equals", "empty", "another"],
133+
0: "tag",
134+
1: "equals"
135+
});
136+
});
137+
});
50138
});

packages/shared/filter-commons/src/condition-utils.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,58 @@ export function restoreArray(cond: FilterCondition | undefined, meta: string): A
142142
return arr;
143143
}
144144

145+
type ReduceMapMeta = {
146+
[index: number]: string;
147+
length: number;
148+
keys: string[];
149+
};
150+
151+
export function reduceMap(input: Record<string, FilterCondition | undefined>): [FilterCondition | undefined, string] {
152+
const meta: ReduceMapMeta = { length: 0, keys: [] };
153+
const conditions: FilterCondition[] = [];
154+
for (const [key, value] of Object.entries(input)) {
155+
meta.keys.push(key);
156+
if (value !== undefined) {
157+
meta[conditions.length] = key;
158+
conditions.push(value);
159+
}
160+
}
161+
meta.length = conditions.length;
162+
163+
const metaJson = JSON.stringify(meta);
164+
165+
switch (conditions.length) {
166+
case 0:
167+
return [undefined, metaJson];
168+
case 1:
169+
return [conditions[0], metaJson];
170+
default:
171+
return [and(...conditions), metaJson];
172+
}
173+
}
174+
/*
175+
export function restoreMap(
176+
cond: FilterCondition | undefined,
177+
metaJson: string
178+
): Record<string, FilterCondition | undefined> {
179+
const meta = JSON.parse(metaJson) as ReduceMapMeta;
180+
const result: Record<string, FilterCondition | undefined> = {};
181+
const keys = Object.keys(meta).filter(key => key !== "length");
182+
for (const key of keys) {
183+
result[key] = undefined;
184+
}
185+
186+
if (meta.length === 0) {
187+
return result;
188+
}
189+
190+
if (meta.length === 1) {
191+
const key = keys[0];
192+
result[key] = cond;
193+
return result;
194+
}
195+
} */
196+
145197
export function fromCompactArray(cond: FilterCondition): Array<FilterCondition | undefined> {
146198
const tag = isAnd(cond) ? cond.args[0] : cond;
147199

0 commit comments

Comments
 (0)