From 5cb501e60481fb74f38595479c246f7d99d115c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Mon, 7 Jun 2021 11:32:43 +0300 Subject: [PATCH] feat: Support rules as strings (#185) Closes #179. --- src/index.ts | 25 ++++++--- src/types.ts | 7 +++ test/customize.test.ts | 125 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 8 deletions(-) diff --git a/src/index.ts b/src/index.ts index 8fdf6d4..26444ac 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,7 +2,12 @@ import wildcard from "wildcard"; import mergeWith from "./merge-with"; import joinArrays from "./join-arrays"; import unique from "./unique"; -import { CustomizeRule, ICustomizeOptions, Key } from "./types"; +import { + CustomizeRule, + CustomizeRuleString, + ICustomizeOptions, + Key, +} from "./types"; import { isPlainObject, isUndefined } from "./utils"; function merge( @@ -68,7 +73,9 @@ function mergeWithCustomize( }; } -function customizeArray(rules: { [s: string]: CustomizeRule }) { +function customizeArray(rules: { + [s: string]: CustomizeRule | CustomizeRuleString; +}) { return (a: any, b: any, key: Key) => { const matchedRule = Object.keys(rules).find((rule) => wildcard(rule, key)) || ""; @@ -87,12 +94,12 @@ function customizeArray(rules: { [s: string]: CustomizeRule }) { }; } -type Rules = { [s: string]: CustomizeRule | Rules }; +type Rules = { [s: string]: CustomizeRule | CustomizeRuleString | Rules }; function mergeWithRules(rules: Rules) { return mergeWithCustomize({ customizeArray: (a: any, b: any, key: Key) => { - let currentRule: CustomizeRule | Rules = rules; + let currentRule: CustomizeRule | CustomizeRuleString | Rules = rules; key.split(".").forEach((k) => { if (!currentRule) { @@ -122,7 +129,7 @@ function mergeWithRule({ a, b, }: { - currentRule: CustomizeRule | Rules; + currentRule: CustomizeRule | CustomizeRuleString | Rules; a: any; b: any; }) { @@ -159,10 +166,10 @@ function mergeWithRule({ return matches; }); - if(!isPlainObject(ao)){ + if (!isPlainObject(ao)) { return ao; } - + Object.entries(ao).forEach(([k, v]) => { const rule = currentRule; @@ -278,7 +285,9 @@ function last(arr) { return arr[arr.length - 1]; } -function customizeObject(rules: { [s: string]: CustomizeRule }) { +function customizeObject(rules: { + [s: string]: CustomizeRule | CustomizeRuleString; +}) { return (a: any, b: any, key: Key) => { switch (rules[key]) { case CustomizeRule.Prepend: diff --git a/src/types.ts b/src/types.ts index 166ee67..99ef752 100644 --- a/src/types.ts +++ b/src/types.ts @@ -14,3 +14,10 @@ export enum CustomizeRule { Prepend = "prepend", Replace = "replace", } + +export type CustomizeRuleString = + | "match" + | "merge" + | "append" + | "prepend" + | "replace"; diff --git a/test/customize.test.ts b/test/customize.test.ts index cc89eca..cd4f74d 100644 --- a/test/customize.test.ts +++ b/test/customize.test.ts @@ -19,6 +19,54 @@ describe("Merge strategy", function () { }); function mergeStrategySpecificTests(merge) { + it("should work with nested arrays and string for append", function () { + const a = { + module: { + loaders: [ + { + test: /.jsx?$/, + loaders: ["babel"], + exclude: /node_modules/, + }, + ], + }, + }; + const b = { + module: { + loaders: [ + { + test: /.jsx?$/, + loaders: ["react-hot"], + exclude: /node_modules/, + }, + ], + }, + }; + const result = { + module: { + loaders: [ + { + test: /.jsx?$/, + loaders: ["babel"], + exclude: /node_modules/, + }, + { + test: /.jsx?$/, + loaders: ["react-hot"], + exclude: /node_modules/, + }, + ], + }, + }; + + assert.deepStrictEqual( + merge({ + "module.loaders": "append", + })(a, b), + result + ); + }); + it("should work with nested arrays and prepend", function () { const a = { module: { @@ -67,6 +115,54 @@ function mergeStrategySpecificTests(merge) { ); }); + it("should work with nested arrays and string for prepend", function () { + const a = { + module: { + loaders: [ + { + test: /.jsx?$/, + loaders: ["babel"], + exclude: /node_modules/, + }, + ], + }, + }; + const b = { + module: { + loaders: [ + { + test: /.jsx?$/, + loaders: ["react-hot"], + exclude: /node_modules/, + }, + ], + }, + }; + const result = { + module: { + loaders: [ + { + test: /.jsx?$/, + loaders: ["react-hot"], + exclude: /node_modules/, + }, + { + test: /.jsx?$/, + loaders: ["babel"], + exclude: /node_modules/, + }, + ], + }, + }; + + assert.deepStrictEqual( + merge({ + "module.loaders": "prepend", + })(a, b), + result + ); + }); + it("should work with array wildcards", function () { const a = { entry: { @@ -95,4 +191,33 @@ function mergeStrategySpecificTests(merge) { result ); }); + + it("should work with array wildcards and string for replace", function () { + const a = { + entry: { + main: ["./src\\config\\main.ts"], + polyfills: ["./src\\config\\polyfills.ts"], + styles: ["./src\\assets\\styles\\styles.sass"], + }, + }; + const b = { + entry: { + main: ["./src\\config\\main.playground.ts"], + }, + }; + const result = { + entry: { + main: ["./src\\config\\main.playground.ts"], + polyfills: ["./src\\config\\polyfills.ts"], + styles: ["./src\\assets\\styles\\styles.sass"], + }, + }; + + assert.deepStrictEqual( + merge({ + "entry.*": "replace", + })(a, b), + result + ); + }); }