Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Fix TypeScript for webpack 5 #155

Merged
merged 1 commit into from Oct 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 15 additions & 2 deletions README.md
Expand Up @@ -2,9 +2,9 @@

# webpack-merge - Merge designed for Webpack

_webpack-merge_ provides a `merge` function that concatenates arrays and merges objects creating a new object. If functions are encountered, it will execute them, run the results through the algorithm, and then wrap the returned values within a function again.
**webpack-merge** provides a `merge` function that concatenates arrays and merges objects creating a new object. If functions are encountered, it will execute them, run the results through the algorithm, and then wrap the returned values within a function again.

This behavior is particularly useful in configuring webpack although it has uses beyond it. Whenever you need to merge configuration objects, _webpack-merge_ can come in handy.
This behavior is particularly useful in configuring webpack although it has uses beyond it. Whenever you need to merge configuration objects, **webpack-merge** can come in handy.

## **`merge(...configuration | [...configuration])`**

Expand Down Expand Up @@ -241,6 +241,19 @@ assert.deepStrictEqual(

The way it works is that you should annotate fields to match using `match` (or `CustomizeRule.Match` if you are using TypeScript) matching your configuration structure and then use specific strategies to define how particular fields should be transformed.

## Using with TypeScript

**webpack-merge** supports TypeScript out of the box. You should pass `Configuration` type from webpack to it as follows:

```typescript
import { Configuration } from "webpack";
import { merge } from "webpack-merge";

const config = merge<Configuration>({...}, {...});

...
```

## Development

1. `nvm use`
Expand Down
7 changes: 6 additions & 1 deletion helpers/merge-tests.ts
Expand Up @@ -291,7 +291,12 @@ function mergeTests(merge) {
}
};
const enhance = {
plugins: [new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)]
plugins: [
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /moment$/
})
]
};

const result1 = merge(config1, enhance);
Expand Down
3,051 changes: 695 additions & 2,356 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Expand Up @@ -20,12 +20,12 @@
"wildcard": "^2.0.0"
},
"devDependencies": {
"@types/webpack": "^4.41.22",
"@types/estree": "0.0.45",
"husky": "^4.3.0",
"tsdx": "^0.14.0",
"tslib": "^2.0.1",
"typescript": "^4.0.3",
"webpack": "^4.44.2"
"tsdx": "^0.14.1",
"tslib": "^2.0.3",
"typescript": "^4.0.5",
"webpack": "^5.3.2"
},
"repository": {
"type": "git",
Expand Down
23 changes: 15 additions & 8 deletions src/index.ts
@@ -1,26 +1,30 @@
import { Configuration } from "webpack";
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 { isPlainObject } from "./utils";

function merge(
function merge<Configuration extends object>(
firstConfiguration: Configuration | Configuration[],
...configurations: Configuration[]
): Configuration {
return mergeWithCustomize({})(firstConfiguration, ...configurations);
return mergeWithCustomize<Configuration>({})(
firstConfiguration,
...configurations
);
}

function mergeWithCustomize(options: ICustomizeOptions) {
function mergeWithCustomize<Configuration extends object>(
options: ICustomizeOptions
) {
return function mergeWithOptions(
firstConfiguration: Configuration | Configuration[],
...configurations: Configuration[]
): Configuration {
// No configuration at all
if (!firstConfiguration) {
return {};
return {} as Configuration;
}

// @ts-ignore
Expand All @@ -32,15 +36,18 @@ function mergeWithCustomize(options: ICustomizeOptions) {
if (Array.isArray(firstConfiguration)) {
// Empty array
if (firstConfiguration.length === 0) {
return {};
return {} as Configuration;
}

// @ts-ignore
if (firstConfiguration[0].then) {
throw new TypeError("Promises are not supported");
}

return mergeWith(firstConfiguration, joinArrays(options));
return mergeWith(
firstConfiguration,
joinArrays(options)
) as Configuration;
}

return firstConfiguration;
Expand All @@ -49,7 +56,7 @@ function mergeWithCustomize(options: ICustomizeOptions) {
return mergeWith(
[firstConfiguration].concat(configurations),
joinArrays(options)
);
) as Configuration;
};
}

Expand Down
4 changes: 2 additions & 2 deletions src/merge-with.ts
Expand Up @@ -2,7 +2,7 @@ function mergeWith(objects: object[], customizer) {
const [first, ...rest] = objects;
let ret = first;

rest.forEach((a) => {
rest.forEach(a => {
ret = mergeTo(ret, a, customizer);
});

Expand All @@ -14,7 +14,7 @@ function mergeTo(a, b, customizer) {

Object.keys(a)
.concat(Object.keys(b))
.forEach((k) => {
.forEach(k => {
const v = customizer(a[k], b[k], k);

ret[k] = typeof v === "undefined" ? a[k] : v;
Expand Down
65 changes: 34 additions & 31 deletions test/merge-with-customize.test.ts
Expand Up @@ -2,121 +2,124 @@ import assert from "assert";
import webpack from "webpack";
import { mergeWithCustomize } from "../resolve";

describe("Merge", function () {
describe("Merge", function() {
customizeMergeTests(mergeWithCustomize);
});

function customizeMergeTests(merge) {
it("should allow overriding array behavior", function () {
it("should allow overriding array behavior", function() {
const first = {
entry: ["a"],
entry: ["a"]
};
const second = {
entry: ["b"],
entry: ["b"]
};

assert.deepStrictEqual(
merge({
customizeArray(a) {
return a;
},
}
})(first, second),
first
);
});

it("should pass key to array customizer", function () {
it("should pass key to array customizer", function() {
let receivedKey;
const first = {
entry: ["a"],
entry: ["a"]
};
const second = {
entry: ["b"],
entry: ["b"]
};
const result = merge({
customizeArray(a, _, key) {
receivedKey = key;

return a;
},
}
})(first, second);

assert.strictEqual(receivedKey, "entry");
assert.deepStrictEqual(result, first);
});

it("should allow overriding object behavior", function () {
it("should allow overriding object behavior", function() {
const first = {
entry: {
a: "foo",
},
a: "foo"
}
};
const second = {
entry: {
a: "bar",
},
a: "bar"
}
};

assert.deepStrictEqual(
merge({
customizeObject(a) {
return a;
},
}
})(first, second),
first
);
});

it("should pass key to object customizer", function () {
it("should pass key to object customizer", function() {
let receivedKey;
const first = {
entry: {
a: "foo",
},
a: "foo"
}
};
const second = {
entry: {
a: "bar",
},
a: "bar"
}
};
const result = merge({
customizeObject(a, _, key) {
receivedKey = key;

return a;
},
}
})(first, second);

assert.strictEqual(receivedKey, "entry");
assert.deepStrictEqual(result, first);
});

it("should customize plugins", function () {
it("should customize plugins", function() {
let receivedKey;
const config1 = {
plugins: [
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify("development"),
},
NODE_ENV: JSON.stringify("development")
}
}),
new webpack.HotModuleReplacementPlugin(),
],
new webpack.HotModuleReplacementPlugin()
]
};
const config2 = {
plugins: [
new webpack.DefinePlugin({
__CLIENT__: true,
__CLIENT__: true
}),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new webpack.HotModuleReplacementPlugin(),
],
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /moment$/
}),
new webpack.HotModuleReplacementPlugin()
]
};

merge({
customizeArray(_, __, key) {
receivedKey = key;
},
}
})(config1, config2);

assert.strictEqual(receivedKey, "plugins");
Expand Down