Skip to content

Commit 55bfb64

Browse files
kborucinskiprzemyslawzalewski
authored andcommitted
Add object deep merge (#25)
* Add merge function for object module * Normalize line endings
1 parent c68332c commit 55bfb64

20 files changed

+334
-24
lines changed

.npmignore

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
*.md
2+
*.test.js
3+
*.test.ts
14
.all-contributorsrc
25
.babelrc.js
36
.coverage
@@ -9,14 +12,12 @@
912
.npmignore
1013
.prettierignore
1114
.prettierrc
12-
*.test.js
13-
*.test.ts
1415
addExtensions.js
1516
compile.js
1617
document.js
1718
ignore.js
19+
normalizeLineEndings.js
1820
package-lock.json
1921
readme.js
2022
regenerate.js
2123
rollup.config.js
22-
*.md

.prettierignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
.coverage
22
index.cjs.js
33
index.umd.js
4-
.coverage

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3770,6 +3770,34 @@ mapValues(); // ⇒ TODO
37703770
TODO: List questions that may this function answers.
37713771
TODO-END -->
37723772

3773+
#### merge
3774+
3775+
Merges two objects deeply.
3776+
3777+
##### Type signature
3778+
3779+
```
3780+
(a: object, b: object) => object
3781+
```
3782+
3783+
##### Examples
3784+
3785+
```javascript
3786+
merge({ a: 1, b: 3 }, {}); // ⇒ { a: 1, b: 3 }
3787+
```
3788+
3789+
```javascript
3790+
merge({ a: 1, b: 3 }, { b: 7 }); // ⇒ { a: 1, b: 7 }
3791+
```
3792+
3793+
```javascript
3794+
merge({ a: 1, b: 3 }, { b: { d: 8 } }); // ⇒ { a: 1, b: { d: 8 } }
3795+
```
3796+
3797+
```javascript
3798+
merge({ a: 1, b: { c: 3 } }, { b: { d: 8 } }); // ⇒ { a: 1, b: { c: 3, d: 8 } }
3799+
```
3800+
37733801
#### none
37743802

37753803
<!-- TODO-START

ignore.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const ignoredFiles = [
2020
"index.umd.js",
2121
"jest.config.js",
2222
"LICENSE",
23+
"normalizeLineEndings.js",
2324
"package-lock.json",
2425
"package.json",
2526
"readme.js",

normalizeLineEndings.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/* eslint-env node */
2+
// eslint-disable console
3+
import { promises } from "fs";
4+
import path from "path";
5+
import os from "os";
6+
import pQueue from "p-queue";
7+
8+
const CONCURRENCY = Math.max(1, os.cpus().length - 1);
9+
10+
const { default: PQueue } = pQueue;
11+
12+
import ignored from "./ignore.js";
13+
14+
const [, ignoredDirectories] = ignored;
15+
16+
const {
17+
readFile: readFileAsync,
18+
writeFile: writeFileAsync,
19+
readdir: readDirectoryAsync
20+
} = promises;
21+
22+
const [, , cwd = process.cwd()] = process.argv;
23+
const root = cwd;
24+
25+
const main = async cwd => {
26+
console.log(`Normalizing files in ${cwd}...`);
27+
28+
const entries = await readDirectoryAsync(cwd, { withFileTypes: true });
29+
30+
const files = entries.filter(x => x.isFile()).map(x => x.name);
31+
32+
const directories = entries
33+
.filter(x => x.isDirectory())
34+
.map(x => x.name)
35+
.filter(x => !ignoredDirectories.includes(x));
36+
37+
for (const directory of directories) {
38+
await main(path.join(cwd, directory));
39+
}
40+
41+
const processFile = async file => {
42+
const filePath = path.join(cwd, file);
43+
const relativeFilePath = path.relative(root, filePath);
44+
45+
try {
46+
console.log(`Normalizing ${relativeFilePath}...`);
47+
48+
const contents = await readFileAsync(filePath, "utf-8");
49+
50+
const normalized = contents
51+
.split("\n")
52+
.map(x => x.trimEnd())
53+
.join("\n");
54+
55+
await writeFileAsync(filePath, normalized, "utf-8");
56+
} catch (error) {
57+
console.error(error);
58+
59+
process.exit(1);
60+
}
61+
};
62+
63+
const queue = new PQueue({ concurrency: CONCURRENCY });
64+
65+
for (const file of files) {
66+
queue.add(() => processFile(file));
67+
}
68+
69+
await queue.onIdle();
70+
};
71+
72+
main(cwd);

object/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,34 @@ mapValues(); // ⇒ TODO
544544
TODO: List questions that may this function answers.
545545
TODO-END -->
546546

547+
# merge
548+
549+
Merges two objects deeply.
550+
551+
## Type signature
552+
553+
```
554+
(a: object, b: object) => object
555+
```
556+
557+
## Examples
558+
559+
```javascript
560+
merge({ a: 1, b: 3 }, {}); // ⇒ { a: 1, b: 3 }
561+
```
562+
563+
```javascript
564+
merge({ a: 1, b: 3 }, { b: 7 }); // ⇒ { a: 1, b: 7 }
565+
```
566+
567+
```javascript
568+
merge({ a: 1, b: 3 }, { b: { d: 8 } }); // ⇒ { a: 1, b: { d: 8 } }
569+
```
570+
571+
```javascript
572+
merge({ a: 1, b: { c: 3 } }, { b: { d: 8 } }); // ⇒ { a: 1, b: { c: 3, d: 8 } }
573+
```
574+
547575
# none
548576

549577
<!-- TODO-START

object/apply.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import entries from "./entries";
22
import fromEntries from "./fromEntries";
33

4-
export default fs => (...xs) =>
4+
export default (fs: { (...xs: any[]): any }[]) => (...xs: any[]) =>
55
fromEntries(entries(fs).map(([key, value]) => [key, value(...xs)]));

object/entries.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
export default Object.entries ||
2-
(object => Object.keys(object).map(key => [key, object[key]]));
1+
export default Object.entries;

object/entries.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
export default Object.entries ||
2-
(object => Object.keys(object).map(key => [key, object[key]]));
1+
export default Object.entries;

object/fromEntries.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
export default Object.fromEntries ||
2-
(keyValuePairs =>
3-
keyValuePairs.reduce(
4-
(acc, [key, value]) => ({ ...acc, [key]: value }),
5-
{}
6-
));
1+
const fromEntries = keyValuePairs =>
2+
keyValuePairs.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
3+
4+
export default Object.fromEntries || fromEntries;

0 commit comments

Comments
 (0)