Skip to content

Commit 128ece4

Browse files
committed
Update to respect importance at strategy item level
1 parent 5983aa9 commit 128ece4

File tree

2 files changed

+55
-20
lines changed

2 files changed

+55
-20
lines changed

lib/src/normalizer.test.ts

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ describe("normalizeConfig", () => {
2626
},
2727
};
2828
const result = await normalizeConfig(config);
29-
expect(result.rules.exactFields.foo[0].strategies).toEqual(["replace"]);
30-
expect(result.rules.exactFields.bar[0].important).toBe(true);
29+
expect(result.rules.exactFields.foo[0].strategies).toEqual([
30+
{ name: "replace", important: false },
31+
]);
32+
expect(result.rules.exactFields.bar[0].strategies[0].important).toBe(true);
3133
});
3234

3335
it("classifies dotted keys as exact", async () => {
@@ -90,8 +92,12 @@ describe("normalizeConfig", () => {
9092
},
9193
};
9294
const result = await normalizeConfig(config);
93-
expect(result.rules.exact["user.name"][0].strategies).toEqual(["replace"]);
94-
expect(result.rules.exact["user.profile.age"][0].strategies).toEqual(["merge"]);
95+
expect(result.rules.exact["user.name"][0].strategies).toEqual([
96+
{ name: "replace", important: false },
97+
]);
98+
expect(result.rules.exact["user.profile.age"][0].strategies).toEqual([
99+
{ name: "merge", important: false },
100+
]);
95101
});
96102

97103
it("applies include/exclude defaults", async () => {
@@ -130,6 +136,18 @@ describe("normalizeConfig", () => {
130136
expect(result.fileFilter("other/file.ts")).toBe(false);
131137
});
132138

139+
it("fileFilter includes allowed files and excludes others", async () => {
140+
const result = await normalizeConfig({
141+
include: ["src/**/*.json"],
142+
exclude: ["src/ignore/**"],
143+
});
144+
expect(result.fileFilter("src/index.ts")).toBe(false);
145+
expect(result.fileFilter("src/index.json")).toBe(true);
146+
expect(result.fileFilter("src/abc/index.json")).toBe(true);
147+
expect(result.fileFilter("src/ignore/file.ts")).toBe(false);
148+
expect(result.fileFilter("other/file.json")).toBe(false);
149+
});
150+
133151
it("uses basicMatcher by default", async () => {
134152
const result = await normalizeConfig({});
135153
expect(result.matcher).toBe(basicMatcher);
@@ -146,7 +164,7 @@ describe("normalizeConfig", () => {
146164
it("throws if strategy name ends with '!'", async () => {
147165
const config: Config<any> = {
148166
byStrategy: {
149-
"merge!": ["foo"],
167+
"merge!!": ["foo"],
150168
},
151169
};
152170
await expect(normalizeConfig(config)).rejects.toThrow(/must not end with "!"/);
@@ -168,7 +186,7 @@ describe("normalizeConfig", () => {
168186
},
169187
};
170188
const result = await normalizeConfig(config);
171-
expect(result.rules.exactFields.foo[0].important).toBe(true);
189+
expect(result.rules.exactFields.foo[0].strategies[0].important).toBe(true);
172190
});
173191

174192
it("marks important from rules tree key with '!'", async () => {
@@ -180,7 +198,7 @@ describe("normalizeConfig", () => {
180198
},
181199
};
182200
const result = await normalizeConfig(config);
183-
expect(result.rules.exact["user.id"][0].important).toBe(true);
201+
expect(result.rules.exact["user.id"][0].strategies[0].important).toBe(true);
184202
});
185203

186204
it("throws on invalid bracket form with dot", async () => {
@@ -221,7 +239,9 @@ describe("normalizeConfig", () => {
221239
},
222240
};
223241
const result = await normalizeConfig(config);
224-
expect(result.rules.exact["root.child.leaf"][0].strategies).toEqual(["merge"]);
242+
expect(result.rules.exact["root.child.leaf"][0].strategies).toEqual([
243+
{ name: "merge", important: false },
244+
]);
225245
});
226246

227247
it("push appends to same key", async () => {
@@ -232,6 +252,9 @@ describe("normalizeConfig", () => {
232252
},
233253
};
234254
const result = await normalizeConfig(config);
235-
expect(result.rules.exactFields.dup.map(r => r.strategies[0])).toEqual(["merge", "replace"]);
255+
expect(result.rules.exactFields.dup.map(r => r.strategies[0])).toEqual([
256+
{ name: "merge", important: false },
257+
{ name: "replace", important: false },
258+
]);
236259
});
237260
});

lib/src/normalizer.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@
77
import { Matcher, basicMatcher, loadMatcher } from "./matcher";
88
import { BasicMergeStrategies, Config, RuleTree, StrategyFn } from "./types";
99

10-
export interface StrategyList {
11-
strategies: string[];
10+
export interface StrategyItem {
11+
name: string;
1212
important: boolean;
13+
}
14+
15+
export interface StrategyList {
16+
strategies: StrategyItem[]; // instead of string[]
1317
order: number;
1418
source: string;
1519
}
@@ -55,14 +59,13 @@ export const normalizeConfig = async <T extends string = BasicMergeStrategies>(
5559
let order = 0;
5660

5761
if (config.byStrategy) {
58-
for (const [strategy, fields] of Object.entries(config.byStrategy)) {
62+
for (const [rawStrategy, fields] of Object.entries(config.byStrategy)) {
5963
if (!fields) continue;
60-
ensureStrategyNameValid(strategy);
64+
const { name, important: strategyImportant } = parseStrategyName(rawStrategy);
6165
for (const raw of fields as string[]) {
62-
const { key, important } = parseImportance(raw);
66+
const { key, important: keyImportant } = parseImportance(raw);
6367
addRule(rules, key, {
64-
strategies: [strategy],
65-
important,
68+
strategies: [{ name, important: strategyImportant || keyImportant }],
6669
order: order++,
6770
source: key,
6871
});
@@ -71,12 +74,14 @@ export const normalizeConfig = async <T extends string = BasicMergeStrategies>(
7174
}
7275

7376
if (config.rules) {
74-
expandRuleTree(config.rules, [], (pathKey, strategies) => {
75-
strategies.forEach(ensureStrategyNameValid);
76-
const { key, important } = parseImportance(pathKey);
77+
expandRuleTree(config.rules, [], (pathKey, strategyNames) => {
78+
const { key, important: keyImportant } = parseImportance(pathKey);
79+
const strategies = strategyNames.map(s => {
80+
const { name, important } = parseStrategyName(s);
81+
return { name, important: important || keyImportant };
82+
});
7783
addRule(rules, key, {
7884
strategies,
79-
important,
8085
order: order++,
8186
source: key,
8287
});
@@ -110,6 +115,13 @@ const normalizeDefault = <T extends string>(def?: T | T[]): string[] => {
110115
return arr.slice();
111116
};
112117

118+
const parseStrategyName = (raw: string): StrategyItem => {
119+
const important = raw.endsWith("!");
120+
const name = important ? raw.slice(0, -1) : raw;
121+
ensureStrategyNameValid(name); // validate AFTER removing !
122+
return { name, important };
123+
};
124+
113125
const ensureStrategyNameValid = (name: string) => {
114126
if (name.endsWith("!")) {
115127
throw new Error(

0 commit comments

Comments
 (0)